diff --git a/.gitignore b/.gitignore
index cde185cf2cea3df2ed46b7ded928641b730089a4..ac56614b7b9d2173ed98b14bada25995242f6595 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,11 @@ config.json
 dist/*
 build/*
 cache
+src/cfclient.egg-info/*
+src/cfclient/third_party/*
+version.json
+win32install/*.exe
+win32install/cfclient.nsi
 
 # PC client settings
 conf/*
@@ -17,4 +22,4 @@ msvcp90.dll
 
 # PyCharm
 .idea/*
-.DS_Store
\ No newline at end of file
+.DS_Store
diff --git a/.travis.yml b/.travis.yml
index 08b53dc09743c88500d204cb8cc5488c3c5935ab..515c02b9e5c1e0757aa24c187bacc6a4336c6586 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,5 +4,7 @@ python:
   - "2.7"
 services:
   - docker
+before_install:
+  - docker pull bitcraze/builder
 script:
   - docker run --rm -v ${PWD}:/module bitcraze/builder ./tools/build/build
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 72656533afda8f5577353acbee167fa1ce091fc6..7f1044fc60ee82e61598f085356720872cbd5251 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,8 +23,8 @@ The development in this repository aims to follow the [Git flow](http://nvie.com
  - Test your changes and note what OS/version you have tested on
  - Describe the change
  - Refer to any issues it effects
-
-Out goal is to comply with PEP-8, but there's lots of code that's not up to standard. We try our best to comply but since we slack sometimes we can't really enforce it, but at least there's a few things we want to stick to:
+ 
+In your code 
 
  - Don't include name, date or information about the change in the code. That's what Git is for.
  - CamelCase classes, but not functions and variables
@@ -32,8 +32,8 @@ Out goal is to comply with PEP-8, but there's lots of code that's not up to stan
  - 4 spaces indentation
  - When catching exceptions try to make it as specific as possible, it makes it harder for bugs to hide
  - Short variable and function names are ok if the scope is small
+ - PEP8/flake8 compliant
 
 ## CI-server
 
 We use https://travis-ci.org/bitcraze/crazyflie-clients-python for continuous integration.
-Initially we only check some PEP-8 properties, but the goal is to also add unit testing and integration testing. This is an ongoing effort.
\ No newline at end of file
diff --git a/LICENSE.txt b/LICENSE.txt
index 9f38dd479a03c143415698c8f790554915dd0de6..4baefd9a463d5521dcedf901fff69ec3933f62b8 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,350 +1,350 @@
-    ||          ____  _ __                           
- +------+      / __ )(_) /_______________ _____  ___ 
- | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
- +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-  ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-
-        Crazyflie client software
-
-        Copyright (C) 2011-2013 Bitcraze AB
-
-
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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.
-
-  <signature of Ty Coon>, 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 Lesser General
-Public License instead of this License.
+    ||          ____  _ __
+ +------+      / __ )(_) /_______________ _____  ___
+ | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
+ +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
+  ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
+
+        Crazyflie client software
+
+        Copyright (C) 2011-2013 Bitcraze AB
+
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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.
+
+  <signature of Ty Coon>, 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 Lesser General
+Public License instead of this License.
diff --git a/MANIFEST.in b/MANIFEST.in
index 7092f9064c808cbedf0f8c96268bcb7dd60fa913..2151a5f7a24b6d44211d506672a9b9552964dce5 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,5 @@
+include README.md
 recursive-include src/cfclient/configs *.json
 recursive-include src/cfclient/ui *.ui
+recursive-include src/cfclient/resources *
+include src/cfclient/version.json
diff --git a/README.md b/README.md
index 58d20b85d4c39d84524f3b4ebb61756dc151724e..b579eb1d853c35e7fa5ebe704c3eb696b279476d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
-# Crazyflie PC client [![Build Status](https://api.travis-ci.org/bitcraze/crazyflie-clients-python.svg)](https://travis-ci.org/bitcraze/crazyflie-clients-python)
+# Crazyflie PC client [![Build Status](https://api.travis-ci.org/bitcraze/crazyflie-clients-python.svg)](https://travis-ci.org/bitcraze/crazyflie-clients-python) [![Build status](https://ci.appveyor.com/api/projects/status/u2kejdbc9wrexo31?svg=true)](https://ci.appveyor.com/project/bitcraze/crazyflie-clients-python)
+
 
 The Crazyflie PC client enables flashing and controlling the Crazyflie.
 There's also a Python library that can be integrated into other applications
@@ -6,49 +7,75 @@ where you would like to use the Crazyflie.
 
 For more info see our [wiki](http://wiki.bitcraze.se/ "Bitcraze Wiki").
 
-Installation
-------------
-
-## Linux
+Note. The project is currently being reorganized, which means that This
+documentation might become inacurate. You can track the reorganisation work in
+the ticket #227.
 
-To install the Crazyflie PC client in Linux, you can run the setup script with:
+Running from source
+-------------------
 
-```sudo setup_linux.sh```
+The Crazyflie client requires [cflib](https://github.com/bitcraze/crazyflie-lib-python).
+Follow the cflib readme to install it.
 
-This will install the Crazyflie PC client systemwide, create a udev entry for
-the Crazyradio and setup the permissions so that the current user can use the
-radio without root permissions after restarting the computer. For further
-instructions on how to run from source and [install dependencies](https://github.com/SteveClement/crazyflie-clients-python#dependencies) see bellow.
+## Windows (7/8/10)
 
-## Windows
+Running from source on Windows is tested using the [miniconda](http://conda.pydata.org/miniconda.html) python distribution. It is possible to run from any distribution as long as the required packages are installed. Building the windows installer requires Python 3.4 (because ```py2exe``` is not distributed for Python 3.5 yet). The following instructions assumes **Miniconda 32-bit** is installed.
 
-Follow these steps to install the binary distribution on Windows 7/8/10.
- - Download the latest release [here](https://github.com/bitcraze/crazyflie-clients-python/releases) (named cfclient-win32-install-*.exe)
- - Execute the installer. After the install the application will be added to the Start menu.
- - Install the Crazyradio drivers by following [these instructions](https://wiki.bitcraze.io/doc:crazyradio:install_windows_zadig)
+Open a command line windows and move to the crazyflie clients folder (the exact command depends of where the project is cloned):
+```
+cd crazyflie-clients-python
+```
 
-Running from source
--------------------
+Create and activate a Python 3.4 environment with numpy pyqt and pyqtgraph from conda (it is the packages we cannot easily install with pip):
+```
+conda create -y -n cfclient python=3.4 numpy=1.10.1 pyqt pyqtgraph
+activate cfclient
+```
 
-## Windows (7/8/10)
+Download the SDL2.dll windows library:
+```
+python tools\build\prep_windows
+```
 
-Install dependencies. With Windows installers (tested using only 32-bit installs on 64-bit OS):
- - [Python 3.4](https://www.python.org/downloads/windows/) (make sure the pip component is selected when installing)
- - [PyQT4 for Python 3.4](http://www.riverbankcomputing.com/software/pyqt/download)
- - [NumPy for Python 3.4](http://sourceforge.net/projects/numpy/files/NumPy)
- - [SDL2](https://www.libsdl.org/download-2.0.php) (copy SDL2.dll into the client source folder)
+Install the client in development mode:
+```
+pip install -e .[dev]
+```
 
-Then install PyUSB, PyZMQ, PySDL2 and PyQtGraph using pip
+You can now run the clients:
 ```
-C:\Users\bitcraze>\Python34\python.exe -m pip install pyusb==1.0.0b2 pyzmq pysdl2 pyqtgraph
+cfclient
+cfheadless
+cfloader
+cfzmq
 ```
 
-Finally you run the client using the following command
+**NOTE:** To use the Crazyradio you will have to [install the drivers](https://wiki.bitcraze.io/doc:crazyradio:install_windows_zadig)
+
+### Creating Windows installer
+
+When you are able to run from source, you can build the windows executable and installer.
+
+First build the executable
 ```
-\Python34\python bin\cfclient
+python setup.py py2exe
 ```
+**NOTE:** The first time the previous command will fail complaining about a ```PyQt4\uic\port_v2```
+folder. Remove this folder with ```rmdir \Q \S path\to\PyQt4\uic\port_v2```,
+you can copy-paste the folder path from the py2exe error message.
+
 
-**NOTE**: To use the Crazyradio you will have to [install the drivers](https://wiki.bitcraze.io/doc:crazyradio:install_windows_zadig)
+Now you can run the client with ```dist\cfclient.exe```.
+
+To generate the installer you need [nsis](http://nsis.sourceforge.net/) installed and in the path. If you
+are a user of [chocolatey](https://chocolatey.org/) you can install it with ```choco install nsis.portable -version 2.50```,
+otherwise you can just download it and install it manually.
+
+To create the installer:
+```
+python win32install\generate_nsis.py
+makensis win32install\cfclient.nsi
+```
 
 ## Mac OSX
 
@@ -56,7 +83,7 @@ Finally you run the client using the following command
 **IMPORTANT NOTE**: The following will use
 [Homebrew](http://brew.sh/) and its own Python distribution. If
 you have a lot of other 3rd party python stuff already running on your system
-they might or might not affected of this.
+they might or might not be affected by this.
 
 1. [Install the Command Line Tools](https://gist.github.com/derhuerst/1b15ff4652a867391f03#1--install-the-command-line-tools).
 
@@ -87,7 +114,14 @@ they might or might not affected of this.
 
     ```
     brew install libusb
-    pip3 install pysdl2 pyusb pyqtgraph
+    pip3 install pysdl2 pyusb pyqtgraph appdirs
+    ```
+
+1. Install cflib from https://github.com/bitcraze/crazyflie-lib-python
+
+1. Install cfclient to run it from source. From the source folder run:
+    ```
+    pip3 install -e .
     ```
 
 1. You now have all the dependencies needed to run the client. From the source folder, run it with the following command:
@@ -114,12 +148,18 @@ they might or might not affected of this.
     ```
     To install ```pyusb``` from ```pip```, use:
     ```
-    sudo pip install pyusb
+    sudo pip install pyusb appdirs
     ```
     To enable the plotter tab install pyqtgraph, this takes a lot of time:
     ```
     sudo port install py34-pyqtgraph
     ```
+    Install cflib from https://github.com/bitcraze/crazyflie-lib-python
+
+    Install cfclient to run it from source. From the source folder run:
+    ```
+    pip install -e .
+    ```
     You can now run the client from the source folder with
     ```
     python bin/cfclient
@@ -142,10 +182,17 @@ they might or might not affected of this.
 
 ### Launching the GUI application
 
+Install cflib from https://github.com/bitcraze/crazyflie-lib-python
+
+Install cfclient to run it from source. From the source folder run (to install
+for your user only you can add ```--user``` to the command):
+```
+pip3 install -e .
+```
 To launch the GUI application in the source folder type:
 ```python bin/cfclient```
 
-To launch the GUI after a systemwide installation, execute ```cfclient```. 
+To launch the GUI after a systemwide installation, execute ```cfclient```.
 
 ### Dependencies
 
@@ -157,53 +204,41 @@ The Crazyflie PC client has the following dependencies:
 * PyQtGraph
 * ZMQ
 * PyQt4
+* appdirs
 
 Example commands to install these dependencies:
 
-* Fedora (tested for 16 to 18):
+* Fedora:
+
+    ```
+    TODO Please contribute
+    ```
 
-    ```sudo yum install pysdl2 pyusb PyQt4```
+
+* Ubuntu (14.04):
+
+    ```
+    sudo apt-get install python3 python3-pip python3-pyqt4 python3-zmq
+    pip3 install pyusb==1.0.0b2
+    pip3 install pyqtgraph appdirs
+    ```
 
 * Ubuntu (15.04):
 
     ```
     sudo apt-get install python3 python3-pip python3-pyqt4 python3-zmq python3-pyqtgraph
     sudo pip3 install pyusb==1.0.0b2
+    sudo pip3 install appdirs
     ```
 
-* OpenSUSE (tested for 11.3):
+* OpenSUSE:
 
-    ```sudo zypper install python-pysdl2 libusb python-usb```
+    ```
+    TODO Please contribute
+    ```
 
 ### Setting udev permissions
 
-The following steps make it possible to use the USB Radio without being root.
-
-Note: If using a fresh Debian install, you may need to install sudo first
-(executing exit command to exit from root shell first):
-
-```
-su -
-apt-get install sudo
-```
-
-Now, with sudo installed, you should be able to do the following commands
-
-```
-sudo groupadd plugdev
-sudo usermod -a -G plugdev <username>
-```
-
-Create a file named ```/etc/udev/rules.d/99-crazyradio.rules``` and add the
-following:
-```
-SUBSYSTEM=="usb", ATTRS{idVendor}=="1915", ATTRS{idProduct}=="7777", MODE="0664", GROUP="plugdev"
-```
-
-To connect Crazyflie 2.0 via usb, create a file name ```/etc/udev/rules.d/99-crazyflie.rules``` and add the following:
-```
-SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE="0664", GROUP="plugdev"
-```
-
-Restart the computer and you are now able to access the USB radio dongle
-without being root.
+Using Crazyradio on Linux requires that you set udev permissions. See the cflib
+[readme](https://github.com/bitcraze/crazyflie-lib-python#setting-udev-permissions)
+for more information.
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4c8d62bd0b92e4badd64f3a45c10cf1fc3bc1b10
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,26 @@
+version: 1.0.{build}
+init:
+- cmd: set PATH=C:\Miniconda35;C:\Miniconda35\scripts;%PATH%
+install:
+- cmd: >-
+    conda create -y -q -n cfclient python=3.4 numpy=1.10.1 pyqt pyqtgraph
+
+    activate cfclient
+
+    pip install -e .[dev]
+
+    rmdir /Q /S C:\Miniconda35\envs\cfclient\lib\site-packages\PyQt4\uic\port_v2
+
+    python tools\build\prep_windows
+
+    choco install -y nsis.portable -version 2.50
+build_script:
+- cmd: >-
+    python setup.py py2exe
+
+    python win32install\generate_nsis.py
+
+    makensis win32install\cfclient.nsi
+artifacts:
+- path: dist\
+- path: win32install\*.exe
diff --git a/bin/cfclient b/bin/cfclient
index 294e865043a5651b93ad43d3b7e8ab4020e86b49..4e34e85f64766a421843554ec196a6c3b14d02df 100755
--- a/bin/cfclient
+++ b/bin/cfclient
@@ -1,116 +1,5 @@
 #!/usr/bin/env python3
+from cfclient.gui import main
 
-from __future__ import absolute_import
-
-import logging
-import os
-import os.path as _path
-from os.path import expanduser
-import sys
-
-APP_NAME = "cfclient"
-
-
-def init_config_path(isInSource):
-    """
-    Configure path for config files.
-
-    If the program is started in the source folder, use a folder "conf" in the
-    root source directory. Otherwise put it in a directory depending on system
-    architecture and configuration. If the chosen directory does not exist,
-    create it.
-    """
-
-    if isInSource:
-        configPath = _path.join(sys.path[0], "..", "conf")
-    else:
-        prefix = expanduser("~")
-
-        if sys.platform == "linux2":
-            if _path.exists(_path.join(prefix, ".local")):
-                configPath = _path.join(prefix, ".local", APP_NAME)
-            else:
-                configPath = _path.join(prefix, "." + APP_NAME)
-        elif sys.platform == "win32":
-            configPath = _path.join(os.environ['APPDATA'], APP_NAME)
-        elif sys.platform == "darwin":
-            from AppKit import NSSearchPathForDirectoriesInDomains
-            # FIXME: Copy-pasted from StackOverflow, not tested!
-            # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
-            # NSApplicationSupportDirectory = 14
-            # NSUserDomainMask = 1
-            # True for expanding the tilde into a fully qualified path
-            configPath = _path.join(NSSearchPathForDirectoriesInDomains(
-                14, 1, True)[0], APP_NAME)
-        else:
-            # Unknown OS, I hope this is good enough
-            configPath = _path.join(prefix, "." + APP_NAME)
-
-    if not _path.exists(configPath):
-        os.makedirs(configPath)
-
-    return configPath
-
-
-def init_paths():
-    """
-    Make the app work in the source tree.
-
-    This puts the root module folder in sys.path[0] and the config folder in
-    sys.path[1]
-    """
-
-    inSource = False
-
-    if hasattr(sys, "frozen"):
-        if sys.frozen in ('dll', 'console_exe', 'windows_exe'):
-            sys.path[0] = _path.normpath(
-                _path.dirname(_path.realpath(sys.executable)))
-        elif sys.frozen in ('macosx_app',):
-            # FIXME: Copy-pasted from StackOverflow, not tested!
-            # py2app:
-            # Notes on how to find stuff on MAC, by an expert (Bob Ippolito):
-            # http://mail.python.org/pipermail/pythonmac-sig/2004-November/012121.html
-            approot = os.environ['RESOURCEPATH']
-    else:
-        prefix = _path.normpath(
-            _path.join(
-                _path.dirname(_path.realpath(__file__)), '..'))
-
-        src_lib = _path.join(prefix, 'src')
-        share_lib = prefix
-        inSource = False
-        for location in [src_lib, share_lib] + sys.path:
-            main_ui = _path.join(location, 'cfclient', 'ui', 'main.ui')
-            if _path.exists(main_ui):
-                sys.path.insert(0, location)
-                if location == src_lib:
-                    inSource = True
-                break
-
-    if sys.path[0] == "":
-        raise Exception("Cannot find cfclient install folder!")
-
-    if inSource:
-        os.environ["PYSDL2_DLL_PATH"] = os.path.abspath(sys.path[0] + "\..")
-    else:
-        os.environ["PYSDL2_DLL_PATH"] = sys.path[0]
-
-    sys.path.insert(1, init_config_path(inSource))
-
-    # Add paths to modules.
-    sys.path.append(_path.join(src_lib, 'cflib'))
-
-
-if __name__ == '__main__':
-    if sys.version_info < (3,):
-        print("The Crazyflie Python client only works with Python 3+, and "
-              "you are running it using version {}.{}.{}".format(
-                  sys.version_info.major, sys.version_info.minor,
-                  sys.version_info.micro))
-        print("Exiting!")
-        sys.exit(1)
-    init_paths()
-    import cfclient
-
-    cfclient.main()
+if __name__ == "__main__":
+    main()
diff --git a/bin/cfheadless b/bin/cfheadless
index 24bed2b1334381ec14ddcbce190a7e92792e0dac..5d88e4e130a92e5e12c338cb263607d9457f50af 100755
--- a/bin/cfheadless
+++ b/bin/cfheadless
@@ -1,93 +1,5 @@
 #!/usr/bin/env python3
+from cfclient.headless import main
 
-from __future__ import absolute_import
-
-APP_NAME = "cfclient"
-
-
-def init_config_path(isInSource):
-    import sys
-    import os
-    import os.path as _path
-    from os.path import expanduser
-
-    if isInSource:
-        configPath = _path.join(sys.path[0], "..", "conf")
-    else:
-        prefix = expanduser("~")
-
-        if sys.platform == "linux2":
-            if _path.exists(_path.join(prefix, ".local")):
-                configPath = _path.join(prefix, ".local", APP_NAME)
-            else:
-                configPath = _path.join(prefix, "." + APP_NAME)
-        elif sys.platform == "win32":
-            configPath = _path.join(os.environ['APPDATA'], APP_NAME)
-        elif sys.platform == "darwin":
-            from AppKit import NSSearchPathForDirectoriesInDomains
-            # FIXME: Copy-pasted from StackOverflow, not tested!
-            # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
-            # NSApplicationSupportDirectory = 14
-            # NSUserDomainMask = 1
-            # True for expanding the tilde into a fully qualified path
-            configPath = path.join(
-                NSSearchPathForDirectoriesInDomains(14, 1, True)[0], APPNAME)
-        else:
-            # Unknown OS, I hope this is good enough
-            configPath = _path.join(prefix, "." + APP_NAME)
-
-    if not _path.exists(configPath):
-        os.makedirs(configPath)
-
-    return configPath
-
-
-def init_paths():
-    """Make the app work in the source tree.
-       This puts the root module folder in path[0] and the config folder in
-       path[1]"""
-    import sys
-    import os.path as _path
-
-    sys.path = ["", ""] + sys.path
-    inSource = False
-
-    if hasattr(sys, "frozen"):
-        if sys.frozen in ('dll', 'console_exe', 'windows_exe'):
-            sys.path[0] = _path.normpath(
-                _path.dirname(_path.realpath(sys.executable)))
-        elif frozen in ('macosx_app',):
-            # FIXME: Copy-pasted from StackOverflow, not tested!
-            # py2app:
-            # Notes on how to find stuff on MAC, by an expert (Bob Ippolito):
-            # http://mail.python.org/pipermail/pythonmac-sig/2004-November/012121.html
-            approot = os.environ['RESOURCEPATH']
-    else:
-        prefix = _path.normpath(
-            _path.join(_path.dirname(_path.realpath(__file__)), '..'))
-
-        src_lib = _path.join(prefix, 'src')
-        share_lib = prefix
-        inSource = False
-        for location in [src_lib, share_lib] + sys.path:
-            main_ui = _path.join(location, 'cfclient', 'ui', 'main.ui')
-            if _path.exists(main_ui):
-                sys.path[0] = location
-                if location == src_lib:
-                    inSource = True
-                break
-
-    if sys.path[0] == "":
-        raise Exception("Cannot find cfclient install folder!")
-
-    sys.path[1] = init_config_path(inSource)
-
-    # Add paths to modules.
-    sys.path.append(_path.join(src_lib, 'cflib'))
-
-
-if __name__ == '__main__':
-    init_paths()
-    import cfheadless
-
-    cfheadless.main()
+if __name__ == "__main__":
+    main()
diff --git a/bin/cfloader b/bin/cfloader
index 2b68dd209d71477ab2286f772d475bab32ad8276..0def9b718012121a6d6edbe0ca722414efb0644e 100755
--- a/bin/cfloader
+++ b/bin/cfloader
@@ -1,204 +1,5 @@
 #!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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.
+from cfloader import main
 
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-# Crazy Loader bootloader utility
-# Can reset bootload and reset back the bootloader
-
-import sys
-import os
-# Fix the path so imports works regardless from where it's run
-sys.path[0] = os.path.join(sys.path[0][:-4], "src/cflib")
-
-import cflib.crtp  # noqa
-from cflib.bootloader import Bootloader  # noqa
-from cflib.bootloader.boottypes import BootVersion, TargetTypes, Target  # noqa
-
-# Initialise the CRTP link driver
-link = None
-cload = None
-try:
-    cflib.crtp.init_drivers()
-    link = cflib.crtp.get_link_driver("radio://")
-except Exception as e:
-    print("Error: {}".format(str(e)))
-    if link:
-        link.close()
-    sys.exit(-1)
-
-# Set the default parameters
-# Default to Arnaud's copter
-cpu_id = "32:00:6e:06:58:37:35:32:60:58:01:43"
-clink = None
-action = "info"
-boot = "cold"
-
-if len(sys.argv) < 2:
-    print()
-    print("==============================")
-    print(" CrazyLoader Flash Utility")
-    print("==============================")
-    print()
-    print(" Usage:", sys.argv[0], "[CRTP options] <action> [parameters]")
-    print()
-    print("The CRTP options are described above")
-    print()
-    print("Crazyload option:")
-    print("   info                    : Print the info of the bootloader "
-          "and quit.")
-    print("                             Will let the target in bootloader "
-          "mode")
-    print("   reset                   : Reset the device in firmware mode")
-    print("   flash <file> [targets]  : flash the <img> binary file from "
-          "the first")
-    print("                             possible  page in flash and reset "
-          "to firmware")
-    print("                             mode.")
-    if link:
-        link.close()
-    sys.exit(0)
-
-# Analyse the command line parameters
-sys.argv = sys.argv[1:]
-argv = []
-
-warm_uri = None
-
-i = 0
-while i < len(sys.argv):
-    if sys.argv[i] == "-i":
-        i += 1
-        cpu_id = sys.argv[i]
-    elif sys.argv[i] == "--cold-boot" or sys.argv[i] == "-c":
-        boot = "cold"
-    elif sys.argv[i] == "--warm-boot" or sys.argv[i] == "-w":
-        boot = "reset"
-        i += 1
-        clink = sys.argv[i]
-    else:
-        argv += [sys.argv[i]]
-    i += 1
-sys.argv = argv
-
-# Analyse the command
-if len(sys.argv) < 1:
-    action = "info"
-elif sys.argv[0] == "info":
-    action = "info"
-elif sys.argv[0] == "reset":
-    action = "reset"
-elif sys.argv[0] == "flash":
-    # print len(sys.argv)
-    if len(sys.argv) < 2:
-        print("The flash action require a file name.")
-        link.close()
-        sys.exit(-1)
-    action = "flash"
-    filename = sys.argv[1]
-    targetnames = {}
-    for t in sys.argv[2:]:
-        [target, type] = t.split("-")
-        if target in targetnames:
-            targetnames[target] += (type,)
-        else:
-            targetnames[target] = (type,)
-else:
-    print("Action", sys.argv[0], "unknown!")
-    link.close()
-    sys.exit(-1)
-
-# Currently there's two different targets available
-targets = ()
-
-try:
-    # Initialise the bootloader lib
-    bl = Bootloader(clink)
-
-    #########################################
-    # Get the connection with the bootloader
-    #########################################
-    # The connection is done by reseting to the bootloader (default)
-    if boot == "reset":
-        print("Reset to bootloader mode ..."),
-        sys.stdout.flush()
-        if bl.start_bootloader(warm_boot=True):
-            print(" done!")
-        else:
-            print("Failed to warmboot")
-            bl.close()
-            sys.exit(-1)
-    else:  # The connection is done by a cold boot ...
-        print("Restart the Crazyflie you want to bootload in the next"),
-        print(" 10 seconds ..."),
-
-        sys.stdout.flush()
-        if bl.start_bootloader(warm_boot=False):
-            print(" done!")
-        else:
-            print("Cannot connect the bootloader!")
-            bl.close()
-            sys.exit(-1)
-
-    print("Connected to bootloader on {} (version=0x{:X})".format(
-        BootVersion.to_ver_string(bl.protocol_version),
-        bl.protocol_version))
-
-    if bl.protocol_version == BootVersion.CF2_PROTO_VER:
-        targets += (bl.get_target(TargetTypes.NRF51),)
-    targets += (bl.get_target(TargetTypes.STM32),)
-
-    ######################################
-    # Doing something (hopefully) useful
-    ######################################
-
-    # Print information about the targets
-    for target in targets:
-        print(target)
-    if action == "info":
-        None  # Already done ...
-    elif action == "reset":
-        print
-        print("Reset in firmware mode ...")
-        bl.reset_to_firmware()
-    elif action == "flash":
-        bl.flash(filename, targetnames)
-        print("Reset in firmware mode ...")
-        bl.reset_to_firmware()
-    else:
-        None
-except Exception as e:
-    import traceback
-
-    traceback.print_exc(file=sys.stdout)
-    print(e)
-
-finally:
-    #########################
-    # Closing the connection
-    #########################
-    if bl:
-        bl.close()
+if __name__ == "__main__":
+    main()
diff --git a/bin/cfzmq b/bin/cfzmq
index 3881a98a459f8d67e6201327ba94a93135496432..8cffe898d0d982f2232f06bb3f58fca75b795fec 100755
--- a/bin/cfzmq
+++ b/bin/cfzmq
@@ -1,93 +1,5 @@
 #!/usr/bin/env python3
+from cfzmq import main
 
-from __future__ import absolute_import
-
-APP_NAME = "cfzmq"
-
-
-def init_config_path(isInSource):
-    import sys
-    import os
-    import os.path as _path
-    from os.path import expanduser
-
-    if isInSource:
-        configPath = _path.join(sys.path[0], "..", "conf")
-    else:
-        prefix = expanduser("~")
-
-        if sys.platform == "linux2":
-            if _path.exists(_path.join(prefix, ".local")):
-                configPath = _path.join(prefix, ".local", APP_NAME)
-            else:
-                configPath = _path.join(prefix, "." + APP_NAME)
-        elif sys.platform == "win32":
-            configPath = _path.join(os.environ['APPDATA'], APP_NAME)
-        elif sys.platform == "darwin":
-            from AppKit import NSSearchPathForDirectoriesInDomains
-            # FIXME: Copy-pasted from StackOverflow, not tested!
-            # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
-            # NSApplicationSupportDirectory = 14
-            # NSUserDomainMask = 1
-            # True for expanding the tilde into a fully qualified path
-            configPath = path.join(
-                NSSearchPathForDirectoriesInDomains(14, 1, True)[0], APPNAME)
-        else:
-            # Unknown OS, I hope this is good enough
-            configPath = _path.join(prefix, "." + APP_NAME)
-
-    if not _path.exists(configPath):
-        os.makedirs(configPath)
-
-    return configPath
-
-
-def init_paths():
-    """Make the app work in the source tree.
-       This puts the root module folder in path[0] and the config folder in
-       path[1]"""
-    import sys
-    import os.path as _path
-
-    sys.path = ["", ""] + sys.path
-    inSource = False
-
-    if hasattr(sys, "frozen"):
-        if sys.frozen in ('dll', 'console_exe', 'windows_exe'):
-            sys.path[0] = _path.normpath(
-                _path.dirname(_path.realpath(sys.executable)))
-        elif frozen in ('macosx_app',):
-            # FIXME: Copy-pasted from StackOverflow, not tested!
-            # py2app:
-            # Notes on how to find stuff on MAC, by an expert (Bob Ippolito):
-            # http://mail.python.org/pipermail/pythonmac-sig/2004-November/012121.html
-            approot = os.environ['RESOURCEPATH']
-    else:
-        prefix = _path.normpath(
-            _path.join(_path.dirname(_path.realpath(__file__)), '..'))
-
-        src_lib = _path.join(prefix, 'src')
-        share_lib = prefix
-        inSource = False
-        for location in [src_lib, share_lib] + sys.path:
-            main_ui = _path.join(location, 'cfclient', 'ui', 'main.ui')
-            if _path.exists(main_ui):
-                sys.path[0] = location
-                if location == src_lib:
-                    inSource = True
-                break
-
-    if sys.path[0] == "":
-        raise Exception("Cannot find cfclient install folder!")
-
-    sys.path[1] = init_config_path(inSource)
-
-    # Add paths to modules.
-    sys.path.append(_path.join(src_lib, 'cflib'))
-
-
-if __name__ == '__main__':
-    init_paths()
-    import cfzmq
-
-    cfzmq.main()
+if __name__ == "__main__":
+    main()
diff --git a/examples/basiclog.py b/examples/basiclog.py
index 95ac6a0424d4be329489a4b32c85d546715b9085..21a1f3019660a3df6d13d518c7d53b200f72cef3 100644
--- a/examples/basiclog.py
+++ b/examples/basiclog.py
@@ -19,19 +19,16 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston,
 #  MA  02110-1301, USA.
-
 """
 Simple example that connects to the first Crazyflie found, logs the Stabilizer
 and prints it to the console. After 10s the application disconnects and exits.
 """
-
-import sys
 import logging
+import sys
 import time
 from threading import Timer
 
diff --git a/examples/flash-memory.py b/examples/flash-memory.py
index c3003215f85e84cf95f6b0f6868d628ebf6c10ed..da69d0ccd6d04fe97ce782169be0d5a9427cf560 100644
--- a/examples/flash-memory.py
+++ b/examples/flash-memory.py
@@ -39,6 +39,7 @@ class Flasher(object):
     """
     A class that can flash the DS28E05 EEPROM via CRTP.
     """
+
     def __init__(self, link_uri):
         self._cf = Crazyflie()
         self._link_uri = link_uri
diff --git a/examples/read-ow.py b/examples/read-ow.py
index 54911b3d433a4ed8058dc1cde7872884a7c566b7..94c714bd0e27eb451a78d554e83037a4812c2da9 100644
--- a/examples/read-ow.py
+++ b/examples/read-ow.py
@@ -33,7 +33,6 @@ Simple example that connects to the first Crazyflie found, looks for
 import sys
 import logging
 import time
-from threading import Timer
 
 sys.path.append("../src/cflib")
 import cflib.crtp  # noqa
diff --git a/examples/write-eeprom.py b/examples/write-eeprom.py
index bc455b2cb7780f359ac87fb37dd5d63cbd5b3e71..9097bb25e52586c58aa9136c31203c7a6fb171d3 100644
--- a/examples/write-eeprom.py
+++ b/examples/write-eeprom.py
@@ -19,21 +19,17 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston,
 #  MA  02110-1301, USA.
-
 """
 Simple example that connects to the first Crazyflie found, looks for
 EEPROM memories and writes the default values in it.
 """
-
-import sys
 import logging
+import sys
 import time
-from threading import Timer
 
 sys.path.append("../src/cflib")
 import cflib.crtp  # noqa
@@ -92,8 +88,8 @@ class EEPROMExample:
             mems[0].write_data(self._data_written)
 
     def _data_written(self, mem, addr):
-            print("Data written, reading back...")
-            mem.update(self._data_updated)
+        print("Data written, reading back...")
+        mem.update(self._data_updated)
 
     def _data_updated(self, mem):
         print("Updated id={}".format(mem.id))
diff --git a/examples/write-ow.py b/examples/write-ow.py
index e4fb04117fc1a21211be73c2c973d56261ae1671..9f28271af42dfa81590335bc4fd9f4dbb2f587fc 100644
--- a/examples/write-ow.py
+++ b/examples/write-ow.py
@@ -33,7 +33,6 @@ EEPROM memories and lists its contents.
 import sys
 import logging
 import time
-from threading import Timer
 
 sys.path.append("../src/cflib")
 import cflib.crtp  # noqa
@@ -92,8 +91,8 @@ class EEPROMExample:
             mems[0].write_data(self._data_written)
 
     def _data_written(self, mem, addr):
-            print("Data written, reading back...")
-            mem.update(self._data_updated)
+        print("Data written, reading back...")
+        mem.update(self._data_updated)
 
     def _data_updated(self, mem):
         print("Updated id={}".format(mem.id))
diff --git a/examples/zmqclientinput.py b/examples/zmqclientinput.py
index 775f5dd5fdb9e269e5f9170f0b36e5319d22c215..e9667391959b93105f3d48dee8c1cc8f2908fd77 100644
--- a/examples/zmqclientinput.py
+++ b/examples/zmqclientinput.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 # Original code from rshum19
 
 
diff --git a/examples/zmqclientparam.py b/examples/zmqclientparam.py
index c3560fee18ccf4bfebf6b90d383a1f8d4493f42c..13604eb0d20c05b7d93821fabc2e441069963992 100644
--- a/examples/zmqclientparam.py
+++ b/examples/zmqclientparam.py
@@ -20,12 +20,10 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 #  USA.
-
 """
 Test script to show how to use the ZMQ param backend for the Crazyflie
 Python Client. The backend is started automatically in the client if ZMQ
@@ -34,7 +32,6 @@ is available.
 The example will use the buzzer parameters (still testing firmware) and first
 set the buzzer to on (at 4 kHz) for 3 seconds and then turn it off again.
 """
-
 import time
 
 try:
diff --git a/examples/zmqsrvtest.py b/examples/zmqsrvtest.py
index 985dcff090c2c1de557422f6a08849533415d669..100b2741c7f70de23086e67fd9a396bdbb304246 100644
--- a/examples/zmqsrvtest.py
+++ b/examples/zmqsrvtest.py
@@ -45,6 +45,7 @@ except ImportError as e:
 
 
 class _LogThread(Thread):
+
     def __init__(self, socket, *args):
         super(_LogThread, self).__init__(*args)
         self._socket = socket
@@ -65,6 +66,7 @@ class _LogThread(Thread):
 
 
 class _ParamThread(Thread):
+
     def __init__(self, socket, *args):
         super(_ParamThread, self).__init__(*args)
         self._socket = socket
@@ -76,6 +78,7 @@ class _ParamThread(Thread):
 
 
 class _ConnThread(Thread):
+
     def __init__(self, socket, *args):
         super(_ConnThread, self).__init__(*args)
         self._socket = socket
@@ -87,6 +90,7 @@ class _ConnThread(Thread):
 
 
 class _CtrlThread(Thread):
+
     def __init__(self, socket, *args):
         super(_CtrlThread, self).__init__(*args)
         self._socket = socket
diff --git a/setup.py b/setup.py
index deaa857b036067edb4271a5a86da99716dfb5484..e2fbf48c926376d258dbe8957367f6ae3d7ea582 100644
--- a/setup.py
+++ b/setup.py
@@ -1,122 +1,169 @@
 #!/usr/bin/env python3
-
-from distutils.core import setup
-import glob
-import os
+# -*- coding: utf-8 -*-
+import subprocess
+from subprocess import PIPE, Popen
+from setuptools import setup, find_packages
+from glob import glob
+import json
+import codecs
 import sys
-from subprocess import Popen, PIPE
-
+import os
 
-# Recover version from Git
 try:
-    process = Popen(["git", "describe", "--tags"], stdout=PIPE)
-    (output, err) = process.communicate()
-    exit_code = process.wait()
-except OSError:
-    raise Exception("Cannot run git: Git is required to generate packages!")
+    import py2exe  # noqa
+except:
+    pass
 
-VERSION = output.strip().decode("UTF-8")
+if sys.version_info < (3, 4):
+    raise "must use python 3.4 or greater"
 
-toplevel_data_files = ['README.md', 'LICENSE.txt']
 
-# Platform specific settings
-if sys.platform.startswith('win32'):
+# Recover version from Git.
+# Returns None if git is not installed or if we are running outside of the git
+# tree
+def get_version():
     try:
-        import py2exe
-    except ImportError:
-        print("Warning: py2exe not usable")
-
-    setup_args = dict(
-        console=[{
-            "script": 'bin/cfclient',
-            "icon_resources": [(1, "bitcraze.ico")]
-        }],
-        options={"py2exe": {
-            "includes": [
-                "sip", "PyQt4",
-                "cfclient.ui.widgets",
-                "cflib.bootloader.cloader",
-                "cfclient.ui.toolboxes.*",
-                "cfclient.ui.*",
-                "cfclient.ui.tabs.*",
-                "cfclient.ui.widgets.*",
-                "cfclient.ui.dialogs.*",
-                "cfclient.utils.input.inputreaders.*",
-                "cfclient.utils.input.inputinterfaces.*",
-                'zmq.backend.cython'],
-            "excludes": [
-                "AppKit",
-                'zmq.libzmq'],
-            'dll_excludes': [
-                'libzmq.pyd'],
-            "skip_archive": True}})
-
-    toplevel_data_files.append('SDL2.dll')
+        process = Popen(["git", "describe", "--tags"], stdout=PIPE)
+        (output, err) = process.communicate()
+        process.wait()
+    except OSError:
+        return None
+
+    if process.returncode != 0:
+        return None
+
+    version = output.strip().decode("UTF-8")
+
+    if subprocess.call(["git", "diff-index", "--quiet", "HEAD"]) != 0:
+        version += "_modified"
+
+    return version
+
+
+def relative(lst, base=''):
+    return list(map(lambda x: base + os.path.basename(x), lst))
+
+VERSION = get_version()
+
+if not VERSION and not os.path.isfile('src/cfclient/version.json'):
+    sys.stderr.write("Git is required to install from source.\n" +
+                     "Please clone the project with Git or use one of the\n" +
+                     "release pachages (either from pip or a binary build).\n")
+    raise Exception("Git required.")
+
+if not VERSION:
+    versionfile = open('src/cfclient/version.json', 'r', encoding='utf8')
+    VERSION = json.loads(versionfile.read())['version']
 else:
-    setup_args = dict(
-        scripts=['bin/cfclient', 'bin/cfheadless'])
+    with codecs.open('src/cfclient/version.json', 'w', encoding='utf8') as f:
+        f.write(json.dumps({'version': VERSION}))
+
+platform_requires = []
+platform_dev_requires = []
+if sys.platform == 'win32' or sys.platform == 'darwin':
+    platform_requires = ['pysdl2']
+if sys.platform == 'win32':
+    platform_dev_requires = ['py2exe', 'jinja2']
+
+# Make a special case when running py2exe to be able to access resources
+if sys.platform == 'win32' and sys.argv[1] == 'py2exe':
+    package_data = {}
+    data_files = [
+        ('', ['README.md', 'src/cfclient/version.json']),
+        ('ui', glob('src/cfclient/ui/*.ui')),
+        ('ui/tabs', glob('src/cfclient/ui/tabs/*.ui')),
+        ('ui/widgets', glob('src/cfclient/ui/widgets/*.ui')),
+        ('ui/toolboxes', glob('src/cfclient/ui/toolboxes/*.ui')),
+        ('ui/dialogs', glob('src/cfclient/ui/dialogs/*.ui')),
+        ('configs', glob('src/cfclient/configs/*.json')),
+        ('configs/input', glob('src/cfclient/configs/input/*.json')),
+        ('configs/log', glob('src/cfclient/configs/log/*.json')),
+        ('', glob('src/cfclient/*.png')),
+        ('resources', glob('src/cfclient/resources/*')),
+        ('third_party', glob('src/cfclient/third_party/*')),
+    ]
+else:
+    package_data = {
+        'cfclient.ui':  relative(glob('src/cfclient/ui/*.ui')),
+        'cfclient.ui.tabs': relative(glob('src/cfclient/ui/tabs/*.ui')),
+        'cfclient.ui.widgets':  relative(glob('src/cfclient/ui/widgets/*.ui')),
+        'cfclient.ui.toolboxes':  relative(glob('src/cfclient/ui/toolboxes/*.ui')),  # noqa
+        'cfclient.ui.dialogs':  relative(glob('src/cfclient/ui/dialogs/*.ui')),
+        'cfclient':  relative(glob('src/cfclient/configs/*.json'), 'configs/') +  # noqa
+                     relative(glob('src/cfclient/configs/input/*.json'), 'configs/input/') +  # noqa
+                     relative(glob('src/cfclient/configs/log/*.json'), 'configs/log/') +  # noqa
+                     relative(glob('src/cfclient/resources/*'), 'resources/') +
+                     relative(glob('src/cfclient/*.png')),
+        '': ['README.md']
+    }
+    data_files = [
+        ('third_party', glob('src/cfclient/third_party/*')),
+    ]
+
 
 # Initial parameters
-setup_args = dict(name='cfclient',
-                  description='Bitcraze Cazyflie nano quadcopter client',
-                  version=VERSION,
-                  author='Bitcraze team',
-                  author_email='contact@bitcraze.se',
-                  url='http://www.bitcraze.se',
-                  package_dir={'': 'lib'},
-                  packages=['cfclient', 'cfclient.ui', 'cfclient.ui.tabs',
-                            'cfclient.ui.toolboxes', 'cfclient.ui.widgets',
-                            'cfclient.utils', 'cfclient.ui.dialogs', 'cflib',
-                            'cflib.bootloader', 'cflib.crazyflie',
-                            'cflib.drivers',
-                            'cflib.utils', 'cflib.crtp',
-                            'cfclient.utils.input',
-                            'cfclient.utils.input.inputinterfaces',
-                            'cfclient.utils.input.mux',
-                            'cfclient.utils.input.inputreaders'],
-                  data_files=[('', toplevel_data_files),
-                              ('cfclient/ui',
-                               glob.glob('src/cfclient/ui/*.ui')),
-                              ('cfclient/ui/tabs',
-                               glob.glob('src/cfclient/ui/tabs/*.ui')),
-                              ('cfclient/ui/widgets',
-                               glob.glob('src/cfclient/ui/widgets/*.ui')),
-                              ('cfclient/ui/toolboxes',
-                               glob.glob('src/cfclient/ui/toolboxes/*.ui')),
-                              ('cfclient/ui/dialogs',
-                               glob.glob('src/cfclient/ui/dialogs/*.ui')),
-                              ('cfclient/configs',
-                               glob.glob('src/cfclient/configs/*.json')),
-                              ('cflib/cache',
-                               glob.glob('src/cflib/cache/*.json')),
-                              ('cfclient/configs/input',
-                               glob.glob('src/cfclient/configs/input/*.json')),
-                              ('cfclient/configs/log',
-                               glob.glob('src/cfclient/configs/log/*.json')),
-                              ('cfclient',
-                               glob.glob('src/cfclient/*.png'))],
-                  **setup_args)
-
-
-# Fetch values from package.xml when using catkin
-if os.getenv('CATKIN_TEST_RESULTS_DIR'):
-    from catkin_pkg.python_setup import generate_distutils_setup
-    # Delete keys which should not match catkin packaged variant
-    for k in ('version', 'url'):
-        setup_args.pop(k, None)
-    setup_args = generate_distutils_setup(**setup_args)
-
-
-# Write a temp file to pass verision into script
-version_file = os.path.join(os.path.dirname(__file__),
-                            "lib", "cfclient", "version.py")
-try:
-    with open(version_file, "w") as versionpy:
-        versionpy.write("VERSION='{}'".format(VERSION))
-except:
-    print("Warning: Version file cannot be written.")
+setup(
+    name='cfclient',
+    description='Bitcraze Cazyflie quadcopter client',
+    version=VERSION,
+    author='Bitcraze team',
+    author_email='contact@bitcraze.se',
+    url='http://www.bitcraze.io',
+
+    classifiers=[
+        'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',  # noqa
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
+    ],
+
+    keywords='quadcopter crazyflie',
+
+    package_dir={'': 'src'},
+    packages=find_packages('src'),
+
+    entry_points={
+        'console_scripts': [
+            'cfclient=cfclient.gui:main',
+            'cfheadless=cfclient.headless:main',
+            'cfloader=cfloader:main',
+            'cfzmq=cfzmq:main'
+        ],
+    },
+
+    install_requires=platform_requires + ['cflib==0.1.0', 'appdirs==1.4.0',
+                                          'pyzmq'],
+
+    # List of dev dependencies
+    # You can install them by running
+    # $ pip install -e .[dev]
+    extras_require={
+        'dev': platform_dev_requires + []
+    },
+
+    package_data=package_data,
+
+    # Py2exe options
+    console=[
+        {
+            'script': 'bin/cfclient',
+            'icon_resources': [(0, 'bitcraze.ico')]
+        }
+    ],
+    options={
+        "py2exe": {
+            'includes': ['cfclient.ui.widgets.hexspinbox',
+                         'zmq.backend.cython'],
+            'bundle_files': 3,
+            'skip_archive': True,
+        },
+    },
 
-setup(**setup_args)
+    data_files=data_files
+)
 
-if (os.path.isfile(version_file)):
-    os.remove(version_file)
+# Fixing the zmq lib in the windows binary dist folder
+if sys.platform == 'win32' and sys.argv[1] == 'py2exe':
+    print("Renaming zmq dll")
+    if os.path.isfile('dist/zmq.libzmq.pyd') and \
+       not os.path.isfile('dist/libzmq.pyd'):
+        os.rename('dist/zmq.libzmq.pyd', 'dist/libzmq.pyd')
diff --git a/setup_linux.sh b/setup_linux.sh
deleted file mode 100755
index 648265d533075a717f332a153f8dbf214a9a1bfa..0000000000000000000000000000000000000000
--- a/setup_linux.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-# Install the Crazyflie PC client and set up permissions so that it can be used
-# by the current user immediately
-# Caution! This installs the Crazyflie PC client as root to your Python
-# site-packages directory. If you wish to install it as a normal user, use the
-# instructions on the Wiki at
-# http://wiki.bitcraze.se/projects:crazyflie:pc_utils:install
-# After installation, the Crazyflie PC client can be started with `cfclient`.
-# @author Daniel Lee 2013
-
-# Allow user to use USB radio without root permission
-groupadd plugdev
-usermod -a -G plugdev $USER
-echo SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1915\", ATTRS{idProduct}==\"7777\", \
-MODE=\"0664\", GROUP=\"plugdev\" > /etc/udev/rules.d/99-crazyradio.rules
-echo SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"0483\", ATTRS{idProduct}==\"5740\", \
-MODE=\"0664\", GROUP=\"plugdev\" > /etc/udev/rules.d/99-crazyflie.rules
-
-# Install Crazyflie PC client
-python3 setup.py install
-
diff --git a/src/cfclient/__init__.py b/src/cfclient/__init__.py
index a9b1b5711ab4853df14e42efd489721c75e37dba..bedfb2dc2eff582226b43b7d50c2a4a9789e10fb 100644
--- a/src/cfclient/__init__.py
+++ b/src/cfclient/__init__.py
@@ -24,24 +24,28 @@
 #  this program; if not, write to the Free Software Foundation, Inc., 51
 #  Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-from .cfclient import main
+import os
+from appdirs import AppDirs
+import sys
 
-try:
-    from .version import VERSION
-except:
-    try:
-        import subprocess
+# Path used all over the application
+if not hasattr(sys, 'frozen'):
+    module_path = os.path.dirname(__file__)
+else:
+    module_path = os.path.dirname(sys.executable)
+config_path = AppDirs("cfclient", "Bitcraze").user_config_dir
 
-        VERSION = subprocess.check_output(["git", "describe"]).encode('utf-8')
-    except:
-        VERSION = "dev"
+# Locate the sdl2 lib on Windows (should be in cfclient/thirst_party/)
+if os.name == 'nt':
+    os.environ["PYSDL2_DLL_PATH"] = os.path.join(module_path, "third_party")
 
+if not hasattr(sys, 'frozen'):
+    import pkg_resources
     try:
-        import subprocess
-
-        ret = subprocess.call(["git", "diff", "--quiet", "HEAD"]
-                              ).encode('utf-8')
-        if ret > 0:
-            VERSION += "+"
-    except:
-        VERSION += "+"
+        VERSION = pkg_resources.require("cfclient")[0].version
+    except pkg_resources.DistributionNotFound:
+        VERSION = "dev"
+else:
+    import json
+    with open(os.path.join(module_path, "version.json")) as f:
+        VERSION = json.load(f)['version']
diff --git a/src/cfclient/configs/config.json b/src/cfclient/configs/config.json
index c78d5b0e7948a211fd64f5867b3268ad50c42bf8..bb92591efe544bc86c28072ab1592b17e5516745 100644
--- a/src/cfclient/configs/config.json
+++ b/src/cfclient/configs/config.json
@@ -1,16 +1,16 @@
 {
   "writable" : {
-    "input_device": "", 
-    "link_uri": "", 
-    "flightmode": "Normal", 
-    "open_tabs": "Flight Control", 
-    "trim_pitch": 0.0, 
-    "slew_limit": 45, 
-    "slew_rate": 30, 
-    "trim_roll": 0.0, 
-    "max_thrust": 80, 
-    "min_thrust": 25, 
-    "max_yaw": 200, 
+    "input_device": "",
+    "link_uri": "",
+    "flightmode": "Normal",
+    "open_tabs": "Flight Control",
+    "trim_pitch": 0.0,
+    "slew_limit": 45,
+    "slew_rate": 30,
+    "trim_roll": 0.0,
+    "max_thrust": 80,
+    "min_thrust": 25,
+    "max_yaw": 200,
     "max_rp": 30,
     "client_side_xmode": false,
     "auto_reconnect": false,
@@ -21,11 +21,11 @@
     "enable_zmq_input": false
   },
   "read-only" : {
-    "normal_slew_limit": 45, 
-    "normal_slew_rate": 30, 
-    "normal_max_thrust": 80, 
-    "normal_min_thrust": 25, 
-    "normal_max_yaw": 200, 
+    "normal_slew_limit": 45,
+    "normal_slew_rate": 30,
+    "normal_max_thrust": 80,
+    "normal_min_thrust": 25,
+    "normal_max_yaw": 200,
     "normal_max_rp": 30,
     "default_cf_channel": 10,
     "default_cf_speed": 0,
diff --git a/src/cfclient/configs/input/Joystick.json b/src/cfclient/configs/input/Joystick.json
index 00e1a5edcc90034168d368d62ee81c1a51bfe799..42299c4a3d2e53e8a072b12cabf7d2cc793872a5 100644
--- a/src/cfclient/configs/input/Joystick.json
+++ b/src/cfclient/configs/input/Joystick.json
@@ -1,95 +1,95 @@
-{
-  "inputconfig": {
-    "inputdevice": {
-      "updateperiod": 10, 
-      "springythrottle": false,
-      "name": "Joystick", 
-      "axis": [
-        {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 3, 
-          "key": "thrust", 
-          "name": "thrust"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 2, 
-          "key": "yaw", 
-          "name": "yaw"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 0, 
-          "key": "roll", 
-          "name": "roll"
-        }, 
-        {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 1, 
-          "key": "pitch", 
-          "name": "pitch"
-        }, 
-        {
-          "scale": 1.0,
-          "type": "Input.HAT",
-          "id": 0,
-          "key": "trim",
-          "name": "trim"
-        },
-        {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 4, 
-          "key": "pitchNeg",
-          "name": "pitchNeg"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 5, 
-          "key": "pitchPos",
-          "name": "pitchPos"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 1, 
-          "key": "estop", 
-          "name": "killswitch"
-        }, 
-        {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 2, 
-          "key": "rollNeg",
-          "name": "rollNeg"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 3, 
-          "key": "rollPos",
-          "name": "rollPos"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 0, 
-          "key": "althold", 
-          "name": "althold"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 6, 
-          "key": "exit", 
-          "name": "exitapp"
-        }
-      ]
-    }
-  }
-}
+{
+  "inputconfig": {
+    "inputdevice": {
+      "updateperiod": 10,
+      "springythrottle": false,
+      "name": "Joystick",
+      "axis": [
+        {
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 3,
+          "key": "thrust",
+          "name": "thrust"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 2,
+          "key": "yaw",
+          "name": "yaw"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 0,
+          "key": "roll",
+          "name": "roll"
+        },
+        {
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 1,
+          "key": "pitch",
+          "name": "pitch"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.HAT",
+          "id": 0,
+          "key": "trim",
+          "name": "trim"
+        },
+        {
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 4,
+          "key": "pitchNeg",
+          "name": "pitchNeg"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 5,
+          "key": "pitchPos",
+          "name": "pitchPos"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 1,
+          "key": "estop",
+          "name": "killswitch"
+        },
+        {
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 2,
+          "key": "rollNeg",
+          "name": "rollNeg"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 3,
+          "key": "rollPos",
+          "name": "rollPos"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 0,
+          "key": "althold",
+          "name": "althold"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 6,
+          "key": "exit",
+          "name": "exitapp"
+        }
+      ]
+    }
+  }
+}
diff --git a/src/cfclient/configs/input/PS3_Mode_3.json b/src/cfclient/configs/input/PS3_Mode_3.json
index 18fea8441bbb5dd03427ce8fde66516c725eac68..2a55cb989ae1bccce38274fc5aaf743ec72177d8 100644
--- a/src/cfclient/configs/input/PS3_Mode_3.json
+++ b/src/cfclient/configs/input/PS3_Mode_3.json
@@ -1,83 +1,83 @@
 {
   "inputconfig": {
     "inputdevice": {
-      "updateperiod": 10, 
-      "name": "PS3_Mode_3", 
+      "updateperiod": 10,
+      "name": "PS3_Mode_3",
       "axis": [
         {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 1, 
-          "key": "thrust", 
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 1,
+          "key": "thrust",
           "name": "thrust"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
+          "scale": 1.0,
+          "type": "Input.AXIS",
           "ids": [
-            12, 
+            12,
             13
-          ], 
-          "key": "yaw", 
+          ],
+          "key": "yaw",
           "name": "yaw"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 2, 
-          "key": "roll", 
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 2,
+          "key": "roll",
           "name": "roll"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 3, 
-          "key": "pitch", 
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 3,
+          "key": "pitch",
           "name": "pitch"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 6, 
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 6,
           "key": "pitchNeg",
           "name": "pitchNeg"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 4, 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 4,
           "key": "pitchPos",
           "name": "pitchPos"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 14, 
-          "key": "estop", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 14,
+          "key": "estop",
           "name": "killswitch"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 7, 
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 7,
           "key": "rollNeg",
           "name": "rollNeg"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 5, 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 5,
           "key": "rollPos",
           "name": "rollPos"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 12, 
-          "key": "exit", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 12,
+          "key": "exit",
           "name": "exitapp"
         }
       ]
     }
   }
-}
\ No newline at end of file
+}
diff --git a/src/cfclient/configs/input/PS4_Mode_1.json b/src/cfclient/configs/input/PS4_Mode_1.json
index 15e0010d2107c7e468bcb406b57ab8dd03d624fe..d8c5882570e45450d034d940de953614c1717a4b 100644
--- a/src/cfclient/configs/input/PS4_Mode_1.json
+++ b/src/cfclient/configs/input/PS4_Mode_1.json
@@ -1,87 +1,87 @@
 {
   "inputconfig": {
     "inputdevice": {
-      "updateperiod": 10, 
-      "name": "PS4_Mode_1", 
+      "updateperiod": 10,
+      "name": "PS4_Mode_1",
       "axis": [
         {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 5, 
-          "key": "thrust", 
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 5,
+          "key": "thrust",
           "name": "thrust"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 2, 
-          "key": "yaw", 
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 2,
+          "key": "yaw",
           "name": "yaw"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 0, 
-          "key": "roll", 
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 0,
+          "key": "roll",
           "name": "roll"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 1, 
-          "key": "pitch", 
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 1,
+          "key": "pitch",
           "name": "pitch"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 1, 
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 1,
           "key": "pitchNeg",
           "name": "pitchNeg"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 3, 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 3,
           "key": "pitchPos",
           "name": "pitchPos"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 12, 
-          "key": "estop", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 12,
+          "key": "estop",
           "name": "killswitch"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 0, 
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 0,
           "key": "rollNeg",
           "name": "rollNeg"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 2, 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 2,
           "key": "rollPos",
           "name": "rollPos"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 5, 
-          "key": "althold", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 5,
+          "key": "althold",
           "name": "althold"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 8, 
-          "key": "exit", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 8,
+          "key": "exit",
           "name": "exitapp"
         }
       ]
     }
   }
-}
\ No newline at end of file
+}
diff --git a/src/cfclient/configs/input/PS4_Mode_2.json b/src/cfclient/configs/input/PS4_Mode_2.json
index f369ebdc43d38d99b62872dab2273800f4cd9cac..6b9ef6a15f0510e61deb473b914d81f04e8b2156 100644
--- a/src/cfclient/configs/input/PS4_Mode_2.json
+++ b/src/cfclient/configs/input/PS4_Mode_2.json
@@ -1,87 +1,87 @@
 {
   "inputconfig": {
     "inputdevice": {
-      "updateperiod": 10, 
-      "name": "PS4_Mode_2", 
+      "updateperiod": 10,
+      "name": "PS4_Mode_2",
       "axis": [
         {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 1, 
-          "key": "thrust", 
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 1,
+          "key": "thrust",
           "name": "thrust"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 0, 
-          "key": "yaw", 
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 0,
+          "key": "yaw",
           "name": "yaw"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 2, 
-          "key": "roll", 
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 2,
+          "key": "roll",
           "name": "roll"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 5, 
-          "key": "pitch", 
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 5,
+          "key": "pitch",
           "name": "pitch"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 1, 
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 1,
           "key": "pitchNeg",
           "name": "pitchNeg"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 3, 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 3,
           "key": "pitchPos",
           "name": "pitchPos"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 7, 
-          "key": "estop", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 7,
+          "key": "estop",
           "name": "killswitch"
-        }, 
+        },
         {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": 0, 
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": 0,
           "key": "rollNeg",
           "name": "rollNeg"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 2, 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 2,
           "key": "rollPos",
           "name": "rollPos"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 4, 
-          "key": "althold", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 4,
+          "key": "althold",
           "name": "althold"
-        }, 
+        },
         {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 8, 
-          "key": "exit", 
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 8,
+          "key": "exit",
           "name": "exitapp"
         }
       ]
     }
   }
-}
\ No newline at end of file
+}
diff --git a/src/cfclient/configs/input/xbox360_mode1.json b/src/cfclient/configs/input/xbox360_mode1.json
index 0ca5d032a0763a09979b57d9803a219fefac02a0..5769145688fe4fcbcb93a5449fc83974eededa9a 100644
--- a/src/cfclient/configs/input/xbox360_mode1.json
+++ b/src/cfclient/configs/input/xbox360_mode1.json
@@ -1,87 +1,87 @@
-{
-  "inputconfig": {
-    "inputdevice": {
-      "updateperiod": 10, 
-      "name": "xbox360_mode1_linux", 
-      "axis": [
-        {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 4, 
-          "key": "thrust", 
-          "name": "thrust"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 3, 
-          "key": "yaw", 
-          "name": "yaw"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.AXIS", 
-          "id": 0, 
-          "key": "roll", 
-          "name": "roll"
-        }, 
-        {
-          "scale": -1.0, 
-          "type": "Input.AXIS", 
-          "id": 1, 
-          "key": "pitch", 
-          "name": "pitch"
-        }, 
-        {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": -1, 
-          "key": "pitchNeg",
-          "name": "pitchNeg"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": -1, 
-          "key": "pitchPos",
-          "name": "pitchPos"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": -1, 
-          "key": "estop", 
-          "name": "killswitch"
-        }, 
-        {
-          "scale": -1.0, 
-          "type": "Input.BUTTON", 
-          "id": -1, 
-          "key": "rollNeg",
-          "name": "rollNeg"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": -1, 
-          "key": "rollPos",
-          "name": "rollPos"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": 5, 
-          "key": "althold", 
-          "name": "althold"
-        }, 
-        {
-          "scale": 1.0, 
-          "type": "Input.BUTTON", 
-          "id": -1, 
-          "key": "exit", 
-          "name": "exitapp"
-        }
-      ]
-    }
-  }
-}
\ No newline at end of file
+{
+  "inputconfig": {
+    "inputdevice": {
+      "updateperiod": 10,
+      "name": "xbox360_mode1_linux",
+      "axis": [
+        {
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 4,
+          "key": "thrust",
+          "name": "thrust"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 3,
+          "key": "yaw",
+          "name": "yaw"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.AXIS",
+          "id": 0,
+          "key": "roll",
+          "name": "roll"
+        },
+        {
+          "scale": -1.0,
+          "type": "Input.AXIS",
+          "id": 1,
+          "key": "pitch",
+          "name": "pitch"
+        },
+        {
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": -1,
+          "key": "pitchNeg",
+          "name": "pitchNeg"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": -1,
+          "key": "pitchPos",
+          "name": "pitchPos"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": -1,
+          "key": "estop",
+          "name": "killswitch"
+        },
+        {
+          "scale": -1.0,
+          "type": "Input.BUTTON",
+          "id": -1,
+          "key": "rollNeg",
+          "name": "rollNeg"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": -1,
+          "key": "rollPos",
+          "name": "rollPos"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": 5,
+          "key": "althold",
+          "name": "althold"
+        },
+        {
+          "scale": 1.0,
+          "type": "Input.BUTTON",
+          "id": -1,
+          "key": "exit",
+          "name": "exitapp"
+        }
+      ]
+    }
+  }
+}
diff --git a/src/cfclient/cfclient.py b/src/cfclient/gui.py
similarity index 93%
rename from src/cfclient/cfclient.py
rename to src/cfclient/gui.py
index 901234ab5f03b8df027261756292b68a5bbdad6c..ce27791f061750848fb3304e328d995de8f668a5 100644
--- a/src/cfclient/cfclient.py
+++ b/src/cfclient/gui.py
@@ -33,8 +33,10 @@ import datetime
 
 import logging
 
+import cfclient
+
 __author__ = 'Bitcraze AB'
-__all__ = ['']
+__all__ = []
 
 
 def main():
@@ -56,7 +58,7 @@ def main():
                         help="set debug level "
                              "[minimal, info, debug, debugfile]")
     args = parser.parse_args()
-    globals().update(vars(args))
+    debug = args.debug
 
     cflogger = logging.getLogger('')
 
@@ -80,25 +82,25 @@ def main():
 
     logger = logging.getLogger(__name__)
 
-    logger.debug("Using config path {}".format(sys.path[1]))
+    logger.debug("Using config path {}".format(cfclient.config_path))
     logger.debug("sys.path={}".format(sys.path))
 
     # Try all the imports used in the project here to control what happens....
     try:
-        import usb
+        import usb  # noqa
     except ImportError:
         logger.critical("No pyusb installation found, exiting!")
         sys.exit(1)
 
     if not sys.platform.startswith('linux'):
         try:
-            import sdl2
+            import sdl2  # noqa
         except ImportError:
             logger.critical("No pysdl2 installation found, exiting!")
             sys.exit(1)
 
     try:
-        import PyQt4
+        import PyQt4  # noqa
     except ImportError:
         logger.critical("No PyQT4 installation found, exiting!")
         sys.exit(1)
@@ -135,7 +137,7 @@ def main():
 
     app = QApplication(sys.argv)
 
-    app.setWindowIcon(QIcon(sys.path[0] + "/cfclient/icon-256.png"))
+    app.setWindowIcon(QIcon(cfclient.module_path + "/icon-256.png"))
     # Make sure the right icon is set in Windows 7+ taskbar
     if os.name == 'nt':
         import ctypes
@@ -150,3 +152,6 @@ def main():
     main_window = MainUI()
     main_window.show()
     sys.exit(app.exec_())
+
+if __name__ == "__main__":
+    main()
diff --git a/src/cfheadless.py b/src/cfclient/headless.py
similarity index 95%
rename from src/cfheadless.py
rename to src/cfclient/headless.py
index af359911cc22ba52314d195e9a7b08cec62e2d8b..a4e76b6a437231c45147d12c25d0227e1230547b 100644
--- a/src/cfheadless.py
+++ b/src/cfclient/headless.py
@@ -19,26 +19,22 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston,
 #  MA  02110-1301, USA.
-
 """
 Headless client for the Crazyflie.
 """
-
-import sys
-import os
 import logging
+import os
 import signal
+import sys
 
-import cflib.crtp
-from cflib.crazyflie import Crazyflie
 import cfclient.utils
+import cflib.crtp
 from cfclient.utils.input import JoystickReader
-from cfclient.utils.config import Config
+from cflib.crazyflie import Crazyflie
 
 if os.name == 'posix':
     print('Disabling standard output for libraries!')
@@ -60,8 +56,8 @@ class HeadlessClient():
 
         self._jr = JoystickReader(do_device_discovery=False)
 
-        self._cf = Crazyflie(ro_cache=sys.path[0] + "/cflib/cache",
-                             rw_cache=sys.path[1] + "/cache")
+        self._cf = Crazyflie(ro_cache=None,
+                             rw_cache=cfclient.config_path + "/cache")
 
         signal.signal(signal.SIGINT, signal.SIG_DFL)
 
@@ -78,7 +74,7 @@ class HeadlessClient():
         if (xmode):
             self._cf.commander.set_client_xmode(xmode)
 
-        devs = self._jr.available_devices()
+        devs = self._jr.available_devices()  # noqa, is this a bug?
         print("Will use [%s] for input" % self._devs[input_device])
         self._jr.start_input(self._devs[input_device])
         self._jr.set_input_map(self._devs[input_device], input_config)
@@ -93,7 +89,7 @@ class HeadlessClient():
         for i, dev in enumerate(self._devs):
             print(" - Controller #{}: {}".format(i, dev))
         print("\nAvailable input mapping:")
-        for map in os.listdir(sys.path[1] + '/input'):
+        for map in os.listdir(cfclient.config_path + '/input'):
             print(" - " + map.split(".json")[0])
 
     def connect_crazyflie(self, link_uri):
@@ -171,3 +167,6 @@ def main():
             headless.connect_crazyflie(link_uri=args.uri)
         else:
             print("No input-device connected, exiting!")
+
+if __name__ == "__main__":
+    main()
diff --git a/src/cfclient/ui/dialogs/about.py b/src/cfclient/ui/dialogs/about.py
index 77fd4fe34bbbf84a7245c58f953b6942f3f2cdc6..21aba7403b4cb865f3c103df0c8db9dcc0854eb3 100644
--- a/src/cfclient/ui/dialogs/about.py
+++ b/src/cfclient/ui/dialogs/about.py
@@ -20,32 +20,29 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 The about dialog.
 """
 
 import sys
 
-from PyQt4 import Qt, QtCore, QtGui, uic
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-from PyQt4.Qt import *
-
 import cfclient
-
 import cflib.crtp
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.Qt import *  # noqa
+from PyQt4.QtCore import *  # noqa
+from PyQt4.QtGui import *  # noqa
 
 __author__ = 'Bitcraze AB'
 __all__ = ['AboutDialog']
 
 (about_widget_class,
- about_widget_base_class) = (uic.loadUiType(sys.path[0] +
-                                            '/cfclient/ui/dialogs/about.ui'))
+ about_widget_base_class) = (uic.loadUiType(cfclient.module_path +
+                                            '/ui/dialogs/about.ui'))
 
 DEBUG_INFO_FORMAT = """
 <b>Cfclient</b><br>
@@ -128,7 +125,7 @@ class AboutDialog(QtGui.QWidget, about_widget_class):
         # Open the Credits file and show it in the UI
         credits = ""
         try:
-            with open("CREDITS.txt", 'r') as f:
+            with open("CREDITS.txt", encoding='utf-8', mode='r') as f:
                 for line in f:
                     credits += "{}<br>".format(line)
         except IOError:
diff --git a/src/cfclient/ui/dialogs/bootloader.py b/src/cfclient/ui/dialogs/bootloader.py
index 41f17fbbea5cff9c583ec7a3e7a4cfa6a4713867..a10f3c60b795b34d5a89917b310e46bce2188b30 100644
--- a/src/cfclient/ui/dialogs/bootloader.py
+++ b/src/cfclient/ui/dialogs/bootloader.py
@@ -31,28 +31,20 @@ read/write the configuration block in the Crazyflie flash.
 """
 from cflib.bootloader import Bootloader
 
-import struct
-import sys
-import time
-
 import logging
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
-
-from cfclient.ui.tab import Tab
-
-import cflib.crtp
+from PyQt4 import QtGui, uic
+from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread
 
-from cflib.bootloader.cloader import Cloader
+import cfclient
 
 __author__ = 'Bitcraze AB'
 __all__ = ['BootloaderDialog']
 
 logger = logging.getLogger(__name__)
 
-service_dialog_class = uic.loadUiType(sys.path[0] +
-                                      "/cfclient/ui/dialogs/bootloader.ui")[0]
+service_dialog_class = uic.loadUiType(cfclient.module_path +
+                                      "/ui/dialogs/bootloader.ui")[0]
 
 
 class UIState:
diff --git a/src/cfclient/ui/dialogs/cf1config.py b/src/cfclient/ui/dialogs/cf1config.py
index 752d47845b3b07cc7b29ce4c7934ccb87bd8d9cc..de1ba8b745299a7fff9b6e6eb36b4acbfa39e4f7 100644
--- a/src/cfclient/ui/dialogs/cf1config.py
+++ b/src/cfclient/ui/dialogs/cf1config.py
@@ -31,14 +31,14 @@ read/write the configuration block in the Crazyflie flash.
 """
 
 import struct
-import sys
 from cflib.bootloader import Bootloader
 
 import logging
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+from PyQt4 import QtGui, uic
+from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread
 
+import cfclient
 from cfclient.utils.config import Config
 from functools import reduce
 
@@ -47,8 +47,8 @@ __all__ = ['Cf1ConfigDialog']
 
 logger = logging.getLogger(__name__)
 
-service_dialog_class = uic.loadUiType(sys.path[0] +
-                                      "/cfclient/ui/dialogs/cf1config.ui")[0]
+service_dialog_class = uic.loadUiType(cfclient.module_path +
+                                      "/ui/dialogs/cf1config.ui")[0]
 
 
 class UIState:
diff --git a/src/cfclient/ui/dialogs/cf2config.py b/src/cfclient/ui/dialogs/cf2config.py
index 1f3716fa719473e328fa989a1e9dae9ebbd929de..8ec6ba4e7fb8c4a332fbcfc2fdeeff3282e4c8a0 100644
--- a/src/cfclient/ui/dialogs/cf2config.py
+++ b/src/cfclient/ui/dialogs/cf2config.py
@@ -20,30 +20,29 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 The bootloader dialog is used to update the Crazyflie firmware and to
 read/write the configuration block in the Crazyflie flash.
 """
-
-import sys
 import logging
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+import cfclient
 from cflib.crazyflie.mem import MemoryElement
 
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+
 __author__ = 'Bitcraze AB'
-__all__ = ['CfConfig']
+__all__ = ['Cf2ConfigDialog']
 
 logger = logging.getLogger(__name__)
 
-service_dialog_class = uic.loadUiType(sys.path[0] +
-                                      "/cfclient/ui/dialogs/cf2config.ui")[0]
+service_dialog_class = uic.loadUiType(cfclient.module_path +
+                                      "/ui/dialogs/cf2config.ui")[0]
 
 
 class Cf2ConfigDialog(QtGui.QWidget, service_dialog_class):
diff --git a/src/cfclient/ui/dialogs/inputconfigdialogue.py b/src/cfclient/ui/dialogs/inputconfigdialogue.py
index c45a1bf802961f7982fd7750d28c87438ca2c53b..8e119f47a53eaaccca3c8d6d7e463169ff5a499e 100644
--- a/src/cfclient/ui/dialogs/inputconfigdialogue.py
+++ b/src/cfclient/ui/dialogs/inputconfigdialogue.py
@@ -20,29 +20,24 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 Dialogue used to select and configure an inputdevice. This includes mapping
 buttons and axis to match controls for the Crazyflie.
 """
-
-import sys
 import json
 import logging
 
+import cfclient
 from cfclient.utils.config_manager import ConfigManager
-from cflib.crtp.exceptions import CommunicationException
-
-from PyQt4 import Qt, QtCore, QtGui, uic
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-from PyQt4.Qt import *
-
-from cfclient.utils.input import JoystickReader
+from PyQt4 import Qt
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.Qt import *  # noqa
+from PyQt4.QtCore import *  # noqa
+from PyQt4.QtGui import *  # noqa
 
 __author__ = 'Bitcraze AB'
 __all__ = ['InputConfigDialogue']
@@ -50,11 +45,12 @@ __all__ = ['InputConfigDialogue']
 logger = logging.getLogger(__name__)
 
 (inputconfig_widget_class, connect_widget_base_class) = (
-    uic.loadUiType(sys.path[0] + '/cfclient/ui/dialogs/inputconfigdialogue.ui')
+    uic.loadUiType(cfclient.module_path + '/ui/dialogs/inputconfigdialogue.ui')
 )
 
 
 class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class):
+
     def __init__(self, joystickReader, *args):
         super(InputConfigDialogue, self).__init__(*args)
         self.setupUi(self)
diff --git a/src/cfclient/ui/dialogs/logconfigdialogue.py b/src/cfclient/ui/dialogs/logconfigdialogue.py
index 56300c3566bf548ba58ee7a91281de7462d2f55d..83d2c8f80db1fe4be3dcd2f38d82a9fa3d20ab70 100644
--- a/src/cfclient/ui/dialogs/logconfigdialogue.py
+++ b/src/cfclient/ui/dialogs/logconfigdialogue.py
@@ -31,16 +31,15 @@ enable logging of data from the Crazyflie. These can then be used in different
 views in the UI.
 """
 
-import sys
-import os
 import logging
 
-from PyQt4 import Qt, QtCore, QtGui, uic
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-from PyQt4.Qt import *
+import cfclient
+from PyQt4 import Qt, QtGui, uic
+from PyQt4.QtCore import *  # noqa
+from PyQt4.QtGui import *  # noqa
+from PyQt4.Qt import *  # noqa
 
-from cflib.crazyflie.log import Log, LogVariable, LogConfig
+from cflib.crazyflie.log import LogConfig
 
 __author__ = 'Bitcraze AB'
 __all__ = ['LogConfigDialogue']
@@ -48,7 +47,7 @@ __all__ = ['LogConfigDialogue']
 logger = logging.getLogger(__name__)
 
 (logconfig_widget_class, connect_widget_base_class) = (
-    uic.loadUiType(sys.path[0] + '/cfclient/ui/dialogs/logconfigdialogue.ui'))
+    uic.loadUiType(cfclient.module_path + '/ui/dialogs/logconfigdialogue.ui'))
 
 NAME_FIELD = 0
 ID_FIELD = 1
@@ -57,6 +56,7 @@ CTYPE_FIELD = 3
 
 
 class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class):
+
     def __init__(self, helper, *args):
         super(LogConfigDialogue, self).__init__(*args)
         self.setupUi(self)
diff --git a/src/cfclient/ui/main.py b/src/cfclient/ui/main.py
index 421309356e0c5f271fc2eebced0274c168e6074f..bbca85d0216c819b6b7c8a9072ff148c425e45b3 100644
--- a/src/cfclient/ui/main.py
+++ b/src/cfclient/ui/main.py
@@ -20,47 +20,48 @@
 #  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., 51
 #  Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 The main file for the Crazyflie control application.
 """
-
-import sys
 import logging
+import sys
 
-import PyQt4
-from PyQt4 import QtGui, uic
-from PyQt4.QtCore import pyqtSignal, Qt, pyqtSlot, QDir, QUrl, QThread
-from PyQt4.QtGui import QLabel, QActionGroup, QMessageBox, QAction, \
-    QDesktopServices, QMenu
-
-from .dialogs.inputconfigdialogue import InputConfigDialogue
-from .dialogs.cf2config import Cf2ConfigDialog
-from .dialogs.cf1config import Cf1ConfigDialog
-from cflib.crazyflie import Crazyflie
-from .dialogs.logconfigdialogue import LogConfigDialogue
-
-from cfclient.utils.input import JoystickReader
-from cfclient.utils.zmq_param import ZMQParamAccess
-from cfclient.utils.zmq_led_driver import ZMQLEDDriver
-from cfclient.utils.config import Config
-from cfclient.utils.logconfigreader import LogConfigReader
-from cfclient.utils.config_manager import ConfigManager
-
-import cfclient.ui.toolboxes
+import cfclient
 import cfclient.ui.tabs
+import cfclient.ui.toolboxes
 import cflib.crtp
-
-from cflib.crazyflie.log import Log, LogVariable, LogConfig
-
-from cfclient.ui.dialogs.bootloader import BootloaderDialog
 from cfclient.ui.dialogs.about import AboutDialog
-
+from cfclient.ui.dialogs.bootloader import BootloaderDialog
+from cfclient.utils.config import Config
+from cfclient.utils.config_manager import ConfigManager
+from cfclient.utils.input import JoystickReader
+from cfclient.utils.logconfigreader import LogConfigReader
+from cfclient.utils.zmq_led_driver import ZMQLEDDriver
+from cfclient.utils.zmq_param import ZMQParamAccess
+from cflib.crazyflie import Crazyflie
+from cflib.crazyflie.log import LogConfig
 from cflib.crazyflie.mem import MemoryElement
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+from PyQt4.QtCore import pyqtSlot
+from PyQt4.QtCore import QDir
+from PyQt4.QtCore import QThread
+from PyQt4.QtCore import QUrl
+from PyQt4.QtGui import QAction
+from PyQt4.QtGui import QActionGroup
+from PyQt4.QtGui import QDesktopServices
+from PyQt4.QtGui import QLabel
+from PyQt4.QtGui import QMenu
+from PyQt4.QtGui import QMessageBox
+
+from .dialogs.cf1config import Cf1ConfigDialog
+from .dialogs.cf2config import Cf2ConfigDialog
+from .dialogs.inputconfigdialogue import InputConfigDialogue
+from .dialogs.logconfigdialogue import LogConfigDialogue
 
 __author__ = 'Bitcraze AB'
 __all__ = ['MainUI']
@@ -70,8 +71,8 @@ logger = logging.getLogger(__name__)
 INTERFACE_PROMPT_TEXT = 'Select an interface'
 
 (main_window_class,
- main_windows_base_class) = (uic.loadUiType(sys.path[0] +
-                                            '/cfclient/ui/main.ui'))
+ main_windows_base_class) = (uic.loadUiType(cfclient.module_path +
+                                            '/ui/main.ui'))
 
 
 class MyDockWidget(QtGui.QDockWidget):
@@ -164,8 +165,8 @@ class MainUI(QtGui.QMainWindow, main_window_class):
 
         ######################################################
 
-        self.cf = Crazyflie(ro_cache=sys.path[0] + "/cflib/cache",
-                            rw_cache=sys.path[1] + "/cache")
+        self.cf = Crazyflie(ro_cache=None,
+                            rw_cache=cfclient.config_path + "/cache")
 
         cflib.crtp.init_drivers(enable_debug_driver=Config()
                                 .get("enable_debug_driver"))
@@ -785,8 +786,9 @@ class MainUI(QtGui.QMainWindow, main_window_class):
         self._update_input_device_footer()
 
     def _open_config_folder(self):
-        QDesktopServices.openUrl(QUrl("file:///" +
-                                      QDir.toNativeSeparators(sys.path[1])))
+        QDesktopServices.openUrl(
+            QUrl("file:///" +
+                 QDir.toNativeSeparators(cfclient.config_path)))
 
     def closeAppRequest(self):
         self.close()
diff --git a/src/cfclient/ui/tab.py b/src/cfclient/ui/tab.py
index f31d85eeb534c4f6a8b050102320ce324fdde549..ff49c22e290a0658fbf197fa665487f6602763de 100644
--- a/src/cfclient/ui/tab.py
+++ b/src/cfclient/ui/tab.py
@@ -31,8 +31,8 @@ Superclass for all tabs that implements common functions.
 
 import logging
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+from PyQt4 import QtGui
+from PyQt4.QtCore import pyqtSlot
 
 from cfclient.utils.config import Config
 
@@ -61,7 +61,7 @@ class Tab(QtGui.QWidget):
                 s = Config().get("open_tabs")
                 if (len(s) > 0):
                     s += ","
-            except Exception as e:
+            except Exception:
                 logger.warning("Exception while adding tab to config and "
                                "reading tab config")
             # Check this since tabs in config are opened when app is started
@@ -73,7 +73,7 @@ class Tab(QtGui.QWidget):
             self.tabWidget.removeTab(self.tabWidget.indexOf(self))
             try:
                 parts = Config().get("open_tabs").split(",")
-            except Exception as e:
+            except Exception:
                 logger.warning("Exception while removing tab from config and "
                                "reading tab config")
                 parts = []
diff --git a/src/cfclient/ui/tabs/ConsoleTab.py b/src/cfclient/ui/tabs/ConsoleTab.py
index 29a77bd6990ec74bff96eaad2bca801829bae231..fe0c01aa9b607f9f80d3e158cd1a99ac489fda4a 100644
--- a/src/cfclient/ui/tabs/ConsoleTab.py
+++ b/src/cfclient/ui/tabs/ConsoleTab.py
@@ -29,14 +29,12 @@
 The console tab is used as a console for printouts from the Crazyflie.
 """
 
-import time
-import sys
-
 import logging
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import pyqtSlot, pyqtSignal
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
 
+import cfclient
 from cfclient.ui.tab import Tab
 
 __author__ = 'Bitcraze AB'
@@ -44,8 +42,8 @@ __all__ = ['ConsoleTab']
 
 logger = logging.getLogger(__name__)
 
-console_tab_class = uic.loadUiType(sys.path[0] +
-                                   "/cfclient/ui/tabs/consoleTab.ui")[0]
+console_tab_class = uic.loadUiType(cfclient.module_path +
+                                   "/ui/tabs/consoleTab.ui")[0]
 
 
 class ConsoleTab(Tab, console_tab_class):
diff --git a/src/cfclient/ui/tabs/ExampleTab.py b/src/cfclient/ui/tabs/ExampleTab.py
index 16936bbe29018055812293e0a9e570bfc8c4e703..dd1ff4754f646c0accd1c7c0902c247ff6fce348 100644
--- a/src/cfclient/ui/tabs/ExampleTab.py
+++ b/src/cfclient/ui/tabs/ExampleTab.py
@@ -33,24 +33,21 @@ connects the connected/disconnected callbacks.
 """
 
 import logging
-import sys
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread, Qt
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
 from PyQt4.QtGui import QMessageBox
 
+import cfclient
 from cfclient.ui.tab import Tab
 
-from cflib.crazyflie.log import LogConfig, Log
-from cflib.crazyflie.param import Param
-
 __author__ = 'Bitcraze AB'
 __all__ = ['ExampleTab']
 
 logger = logging.getLogger(__name__)
 
-example_tab_class = uic.loadUiType(sys.path[0] +
-                                   "/cfclient/ui/tabs/exampleTab.ui")[0]
+example_tab_class = uic.loadUiType(cfclient.module_path +
+                                   "/ui/tabs/exampleTab.ui")[0]
 
 
 class ExampleTab(Tab, example_tab_class):
diff --git a/src/cfclient/ui/tabs/FlightTab.py b/src/cfclient/ui/tabs/FlightTab.py
index b2ec43983bf9d3d2323b5ad96bd2d759a467a67c..8a49cf27f5915ed2dfc8a6180dca45327b53672b 100644
--- a/src/cfclient/ui/tabs/FlightTab.py
+++ b/src/cfclient/ui/tabs/FlightTab.py
@@ -29,34 +29,30 @@
 The flight control tab shows telemetry data and flight settings.
 """
 
-import sys
-
 import logging
 
-from time import time
-
-from PyQt4 import QtCore, QtGui, uic
+from PyQt4 import uic
 from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal
 from PyQt4.QtGui import QMessageBox
 
-from cflib.crazyflie import Crazyflie
-
+import cfclient
 from cfclient.ui.widgets.ai import AttitudeIndicator
 
 from cfclient.utils.config import Config
-from cflib.crazyflie.log import Log, LogVariable, LogConfig
+from cflib.crazyflie.log import LogConfig
 
 from cfclient.ui.tab import Tab
 
-from cflib.crazyflie.mem import MemoryElement
+PARAM_NAME_ALT_HOLD_TARGET = "posCtlAlt.targetZ"
+PARAM_NAME_ESTIMATED_Z = "posEstimatorAlt.estimatedZ"
 
 __author__ = 'Bitcraze AB'
 __all__ = ['FlightTab']
 
 logger = logging.getLogger(__name__)
 
-flight_tab_class = uic.loadUiType(sys.path[0] +
-                                  "/cfclient/ui/tabs/flightTab.ui")[0]
+flight_tab_class = uic.loadUiType(cfclient.module_path +
+                                  "/ui/tabs/flightTab.ui")[0]
 
 MAX_THRUST = 65365.0
 
@@ -264,12 +260,13 @@ class FlightTab(Tab, flight_tab_class):
 
     def _baro_data_received(self, timestamp, data, logconf):
         if self.isVisible():
-            self.actualASL.setText(("%.2f" % data["baro.aslLong"]))
-            self.ai.setBaro(data["baro.aslLong"])
+            estimated_z = data[PARAM_NAME_ESTIMATED_Z]
+            self.actualASL.setText(("%.2f" % estimated_z))
+            self.ai.setBaro(estimated_z)
 
     def _althold_data_received(self, timestamp, data, logconf):
         if self.isVisible():
-            target = data["altHold.target"]
+            target = data[PARAM_NAME_ALT_HOLD_TARGET]
             if target > 0:
                 if not self.targetASL.isEnabled():
                     self.targetASL.setEnabled(True)
@@ -340,7 +337,7 @@ class FlightTab(Tab, flight_tab_class):
                 if (not self.logBaro and not self.logAltHold):
                     # The sensor is available, set up the logging
                     self.logBaro = LogConfig("Baro", 200)
-                    self.logBaro.add_variable("baro.aslLong", "float")
+                    self.logBaro.add_variable(PARAM_NAME_ESTIMATED_Z, "float")
 
                     try:
                         self.helper.cf.log.add_config(self.logBaro)
@@ -354,7 +351,8 @@ class FlightTab(Tab, flight_tab_class):
                     except AttributeError as e:
                         logger.warning(str(e))
                     self.logAltHold = LogConfig("AltHold", 200)
-                    self.logAltHold.add_variable("altHold.target", "float")
+                    self.logAltHold.add_variable(PARAM_NAME_ALT_HOLD_TARGET,
+                                                 "float")
 
                     try:
                         self.helper.cf.log.add_config(self.logAltHold)
@@ -510,11 +508,9 @@ class FlightTab(Tab, flight_tab_class):
 
     def alt1_updated(self, state):
         if state:
-            self._ring_effect += 1
-            if self._ring_effect > self._ledring_nbr_effects:
-                self._ring_effect = 0
+            new_index = (self._ring_effect+1) % (self._ledring_nbr_effects+1)
             self.helper.cf.param.set_value("ring.effect",
-                                           str(self._ring_effect))
+                                           str(new_index))
 
     def alt2_updated(self, state):
         self.helper.cf.param.set_value("ring.headlightEnable", str(state))
@@ -526,6 +522,10 @@ class FlightTab(Tab, flight_tab_class):
         except KeyError:
             return
 
+        # Used only in alt1_updated function
+        self._ring_effect = current
+        self._ledring_nbr_effects = nbr
+
         hardcoded_names = {0: "Off",
                            1: "White spinner",
                            2: "Color spinner",
@@ -538,7 +538,8 @@ class FlightTab(Tab, flight_tab_class):
                            9: "Battery status",
                            10: "Boat lights",
                            11: "Alert",
-                           12: "Gravity"}
+                           12: "Gravity",
+                           13: "LED tab"}
 
         for i in range(nbr + 1):
             name = "{}: ".format(i)
@@ -557,6 +558,7 @@ class FlightTab(Tab, flight_tab_class):
             self._led_ring_headlight.setEnabled(True)
 
     def _ring_effect_changed(self, index):
+        self._ring_effect = index
         if index > -1:
             i = self._led_ring_effect.itemData(index)
             logger.info("Changed effect to {}".format(i))
diff --git a/src/cfclient/ui/tabs/GpsTab.py b/src/cfclient/ui/tabs/GpsTab.py
index ad75fcef900648c2c5c6a4947f2450a954e7cd9a..669a4820604d918d56a541fd931a70d665843aa9 100644
--- a/src/cfclient/ui/tabs/GpsTab.py
+++ b/src/cfclient/ui/tabs/GpsTab.py
@@ -20,34 +20,34 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 # USA.
-
 """
 This tab plots different logging data defined by configurations that has been
 pre-configured.
 """
-import math
-
 import logging
-import sys
 
-from PyQt4 import QtCore, QtGui, uic, QtWebKit, QtNetwork
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-from cflib.crazyflie.log import LogConfig
+import cfclient
 from cfclient.ui.tab import Tab
+from cflib.crazyflie.log import LogConfig
+from PyQt4 import QtCore
+from PyQt4 import QtGui
+from PyQt4 import QtNetwork
+from PyQt4 import QtWebKit
+from PyQt4 import uic
+from PyQt4.QtCore import *  # noqa
+from PyQt4.QtGui import *  # noqa
 
 __author__ = 'Bitcraze AB'
 __all__ = ['GpsTab']
 
 logger = logging.getLogger(__name__)
 
-gps_tab_class = uic.loadUiType(sys.path[0] +
-                               "/cfclient/ui/tabs/gpsTab.ui")[0]
+gps_tab_class = uic.loadUiType(cfclient.module_path +
+                               "/ui/tabs/gpsTab.ui")[0]
 
 
 class GpsTab(Tab, gps_tab_class):
@@ -74,13 +74,13 @@ class GpsTab(Tab, gps_tab_class):
         view = self.view = QtWebKit.QWebView()
 
         cache = QtNetwork.QNetworkDiskCache()
-        cache.setCacheDirectory("cache")
+        cache.setCacheDirectory(cfclient.config_path + "/cache")
         view.page().networkAccessManager().setCache(cache)
         view.page().networkAccessManager()
 
         view.page().mainFrame().addToJavaScriptWindowObject("MainWindow", self)
         view.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
-        view.load(QtCore.QUrl(sys.path[0] + "/cfclient/resources/map.html"))
+        view.load(QtCore.QUrl(cfclient.module_path + "/resources/map.html"))
         view.loadFinished.connect(self.onLoadFinished)
         view.linkClicked.connect(QtGui.QDesktopServices.openUrl)
 
@@ -103,7 +103,7 @@ class GpsTab(Tab, gps_tab_class):
         self._max_speed = 0.0
 
     def onLoadFinished(self):
-        with open(sys.path[0] + "/cfclient/resources/map.js", 'r') as f:
+        with open(cfclient.module_path + "/resources/map.js", 'r') as f:
             frame = self.view.page().mainFrame()
             frame.evaluateJavaScript(f.read())
 
@@ -159,8 +159,8 @@ class GpsTab(Tab, gps_tab_class):
 
     def _log_data_received(self, timestamp, data, logconf):
         """Callback when the log layer receives new data"""
-        long = float(data["gps.lon"])/10000000.0
-        lat = float(data["gps.lat"])/10000000.0
+        long = float(data["gps.lon"]) / 10000000.0
+        lat = float(data["gps.lat"]) / 10000000.0
         self._long.setText("{:.6f}".format(long))
         self._lat.setText("{:.6f}".format(lat))
         self._nbr_locked_sats.setText(str(data["gps.nsat"]))
diff --git a/src/cfclient/ui/tabs/LEDTab.py b/src/cfclient/ui/tabs/LEDTab.py
index 5751a278fbced482294b09c949e9f03cafd380d5..452b6c22503e9c912d1d8dbf24d14e71a392a5a3 100644
--- a/src/cfclient/ui/tabs/LEDTab.py
+++ b/src/cfclient/ui/tabs/LEDTab.py
@@ -31,12 +31,11 @@ Basic tab to be able to set (and test) colors in the LED-ring.
 """
 
 import logging
-import sys
 
 from PyQt4 import QtGui, uic
 from PyQt4.QtCore import pyqtSignal
-from PyQt4.QtGui import QColorDialog
 
+import cfclient
 from cfclient.ui.tab import Tab
 
 from cflib.crazyflie.mem import MemoryElement
@@ -46,8 +45,8 @@ __all__ = ['LEDTab']
 
 logger = logging.getLogger(__name__)
 
-led_tab_class = uic.loadUiType(sys.path[0] +
-                               "/cfclient/ui/tabs/ledTab.ui")[0]
+led_tab_class = uic.loadUiType(cfclient.module_path +
+                               "/ui/tabs/ledTab.ui")[0]
 
 
 class LEDTab(Tab, led_tab_class):
@@ -115,8 +114,14 @@ class LEDTab(Tab, led_tab_class):
             self._intensity_slider.setValue)
 
     def _select(self, nbr):
-        col = QColorDialog()
-        col = QtGui.QColorDialog.getColor()
+        col = QtGui.QColor()  # default to invalid
+
+        if self._mem:
+            led = self._mem.leds[nbr]
+            col = QtGui.QColor.fromRgb(led.r, led.g, led.b)
+
+        col = QtGui.QColorDialog.getColor(col)
+
         if col.isValid() and self._mem:
             logger.info(col.red())
             self._mem.leds[nbr].set(r=col.red(), g=col.green(), b=col.blue())
diff --git a/src/cfclient/ui/tabs/LogBlockDebugTab.py b/src/cfclient/ui/tabs/LogBlockDebugTab.py
index 17abd4ed81d248f1e3714ed7a7a2f9d2fb49aa24..f827db03fe3bc81794b2b9a7f98f5fed52da016b 100644
--- a/src/cfclient/ui/tabs/LogBlockDebugTab.py
+++ b/src/cfclient/ui/tabs/LogBlockDebugTab.py
@@ -30,19 +30,17 @@ Shows all the parameters available in the Crazyflie and also gives the ability
 to edit them.
 """
 
-import time
-import sys
-
 from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+from PyQt4.QtCore import Qt, pyqtSignal
 
+import cfclient
 from cfclient.ui.tab import Tab
 
 __author__ = 'Bitcraze AB'
-__all__ = ['LogBlockTab']
+__all__ = ['LogBlockDebugTab']
 
-logblock_tab_class = uic.loadUiType(sys.path[0] +
-                                    "/cfclient/ui/tabs/logBlockDebugTab.ui")[0]
+logblock_tab_class = uic.loadUiType(cfclient.module_path +
+                                    "/ui/tabs/logBlockDebugTab.ui")[0]
 
 
 class LogBlockDebugTab(Tab, logblock_tab_class):
diff --git a/src/cfclient/ui/tabs/LogBlockTab.py b/src/cfclient/ui/tabs/LogBlockTab.py
index a210102fb5d54eac49f9a2b3c3f0a6a7c7a3c826..4094375732729e46b548ea271a9046881cb64d8c 100644
--- a/src/cfclient/ui/tabs/LogBlockTab.py
+++ b/src/cfclient/ui/tabs/LogBlockTab.py
@@ -31,19 +31,16 @@ This tab shows all log blocks that are registered and can be used to start the
 logging and also to write the logging data to file.
 """
 
-import sys
-
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+from PyQt4 import uic
+from PyQt4.QtCore import Qt, pyqtSignal
 
+import cfclient
 from cfclient.ui.tab import Tab
 
 import logging
 
 from PyQt4.QtGui import QApplication, QStyledItemDelegate, QAbstractItemView
 from PyQt4.QtGui import QStyleOptionButton, QStyle
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread
 from PyQt4.QtCore import QAbstractItemModel, QModelIndex
 
 from cfclient.utils.logdatawriter import LogWriter
@@ -52,7 +49,7 @@ __author__ = 'Bitcraze AB'
 __all__ = ['LogBlockTab']
 
 logblock_tab_class = uic.loadUiType(
-    sys.path[0] + "/cfclient/ui/tabs/logBlockTab.ui")[0]
+    cfclient.module_path + "/ui/tabs/logBlockTab.ui")[0]
 
 logger = logging.getLogger(__name__)
 
@@ -167,6 +164,7 @@ class LogBlockItem(object):
 
 
 class LogBlockModel(QAbstractItemModel):
+
     def __init__(self, view, parent=None):
         super(LogBlockModel, self).__init__(parent)
         self._nodes = []
diff --git a/src/cfclient/ui/tabs/LogTab.py b/src/cfclient/ui/tabs/LogTab.py
index 5a173c27ba74d77bdf002e0bc18fb0e3344eb943..760d2f83d3d1974c71ecb13f6e9d832849f754c9 100644
--- a/src/cfclient/ui/tabs/LogTab.py
+++ b/src/cfclient/ui/tabs/LogTab.py
@@ -20,30 +20,26 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 Shows the Log TOC of available variables in the Crazyflie.
 """
 
-import time
-import sys
-
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
-
-from cflib.crazyflie import Crazyflie
-
+import cfclient
 from cfclient.ui.tab import Tab
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+from PyQt4.QtCore import pyqtSlot
+from PyQt4.QtCore import Qt
 
 __author__ = 'Bitcraze AB'
 __all__ = ['LogTab']
 
-param_tab_class = uic.loadUiType(sys.path[0] +
-                                 "/cfclient/ui/tabs/logTab.ui")[0]
+param_tab_class = uic.loadUiType(cfclient.module_path +
+                                 "/ui/tabs/logTab.ui")[0]
 
 
 class LogTab(Tab, param_tab_class):
diff --git a/src/cfclient/ui/tabs/ParamTab.py b/src/cfclient/ui/tabs/ParamTab.py
index 23e295e7eda48bff8c9ae07f597a61fcecfc03f7..4ac4dc817a628949a4b202a53083b1c4b828316d 100644
--- a/src/cfclient/ui/tabs/ParamTab.py
+++ b/src/cfclient/ui/tabs/ParamTab.py
@@ -30,23 +30,21 @@ Shows all the parameters available in the Crazyflie and also gives the ability
 to edit them.
 """
 
-import sys
 import logging
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+from PyQt4 import uic
+from PyQt4.QtCore import Qt, pyqtSignal
 from PyQt4.QtCore import QAbstractItemModel, QModelIndex
-from PyQt4.QtGui import QApplication, QStyledItemDelegate, QAbstractItemView, \
-    QBrush, QColor
-from PyQt4.QtGui import QSortFilterProxyModel
+from PyQt4.QtGui import QBrush, QColor
 
+import cfclient
 from cfclient.ui.tab import Tab
 
 __author__ = 'Bitcraze AB'
 __all__ = ['ParamTab']
 
 param_tab_class = uic.loadUiType(
-    sys.path[0] + "/cfclient/ui/tabs/paramTab.ui")[0]
+    cfclient.module_path + "/ui/tabs/paramTab.ui")[0]
 
 logger = logging.getLogger(__name__)
 
diff --git a/src/cfclient/ui/tabs/PlotTab.py b/src/cfclient/ui/tabs/PlotTab.py
index 93a169c244e162e9ecb4aa27f8dac17aae224279..6477b254d7bced2465b4e4f355bc1880fa930a0f 100644
--- a/src/cfclient/ui/tabs/PlotTab.py
+++ b/src/cfclient/ui/tabs/PlotTab.py
@@ -20,44 +20,34 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 This tab plots different logging data defined by configurations that has been
 pre-configured.
 """
 
-import glob
-import json
 import logging
-import os
-import sys
-
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread, Qt
-from PyQt4.QtGui import QMessageBox
-from PyQt4.QtGui import QApplication, QStyledItemDelegate, QAbstractItemView
-from PyQt4.QtCore import QAbstractItemModel, QModelIndex
-
-from pprint import pprint
-import datetime
 
+from cfclient.ui.tab import Tab
 from cfclient.ui.widgets.plotwidget import PlotWidget
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+from PyQt4.QtCore import QAbstractItemModel
+from PyQt4.QtCore import QModelIndex
+from PyQt4.QtCore import Qt
+from PyQt4.QtGui import QMessageBox
 
-from cflib.crazyflie.log import Log
-
-from cfclient.ui.tab import Tab
+import cfclient
 
 __author__ = 'Bitcraze AB'
 __all__ = ['PlotTab']
 
 logger = logging.getLogger(__name__)
 
-plot_tab_class = uic.loadUiType(sys.path[0] +
-                                "/cfclient/ui/tabs/plotTab.ui")[0]
+plot_tab_class = uic.loadUiType(cfclient.module_path +
+                                "/ui/tabs/plotTab.ui")[0]
 
 
 class LogConfigModel(QAbstractItemModel):
@@ -87,7 +77,7 @@ class LogConfigModel(QAbstractItemModel):
         """Re-implemented method to get the number of rows for a given index"""
         parent_item = parent.internalPointer()
         if parent.isValid():
-            parent_item = parent.internalPointer()
+            parent_item = parent.internalPointer()  # noqa
             return 0
         else:
             return len(self._nodes)
@@ -106,7 +96,7 @@ class LogConfigModel(QAbstractItemModel):
 
     def data(self, index, role):
         """Re-implemented method to get the data for a given index and role"""
-        node = index.internalPointer()
+        node = index.internalPointer()  # noqa
         if not index.isValid() or not 0 <= index.row() < len(self._nodes):
             return None
         if role == Qt.DisplayRole:
diff --git a/src/cfclient/ui/tabs/__init__.py b/src/cfclient/ui/tabs/__init__.py
index c11b4da6fc7cc92ce1fc0aff69a7a38e0c00568c..7eb126ac69e4be83a2571b868f30a0bc1045d1f4 100644
--- a/src/cfclient/ui/tabs/__init__.py
+++ b/src/cfclient/ui/tabs/__init__.py
@@ -20,11 +20,9 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 Find all the available tabs so they can be loaded.
 
@@ -32,26 +30,27 @@ Dropping a new .py file into this directory will automatically list and load
 it into the UI when it is started.
 """
 
-import os
-import glob
-import logging
+from .ConsoleTab import ConsoleTab
+# from .ExampleTab import ExampleTab
+from .FlightTab import FlightTab
+from .GpsTab import GpsTab
+from .LEDTab import LEDTab
+from .LogBlockTab import LogBlockTab
+from .LogTab import LogTab
+from .ParamTab import ParamTab
+from .PlotTab import PlotTab
 
 __author__ = 'Bitcraze AB'
 __all__ = []
 
-logger = logging.getLogger(__name__)
-
-found_tabs = [os.path.splitext(os.path.basename(f))[0] for
-              f in glob.glob(os.path.dirname(__file__) + "/[A-Za-z]*Tab.py")]
-if len(found_tabs) == 0:
-    found_tabs = [os.path.splitext(os.path.basename(f))[0] for
-                  f in glob.glob(os.path.dirname(__file__) +
-                                 "/[A-Za-z]*Tab.pyc")]
-
-logger.debug("Found tabs: %s", found_tabs)
-
-available = []
-
-for tab in found_tabs:
-    tabModule = __import__(tab, globals(), locals(), [tab], 1)
-    available.append(getattr(tabModule, tab))
+available = [
+    ConsoleTab,
+    # ExampleTab,
+    FlightTab,
+    GpsTab,
+    LEDTab,
+    LogBlockTab,
+    LogTab,
+    ParamTab,
+    PlotTab,
+]
diff --git a/src/cfclient/ui/toolboxes/ConsoleToolbox.py b/src/cfclient/ui/toolboxes/ConsoleToolbox.py
index ce6659e08c8219fba78311c4f7af6bca8e92e37f..82faa3cc58aef0742f0a12b9ee52e4f242ee7166 100644
--- a/src/cfclient/ui/toolboxes/ConsoleToolbox.py
+++ b/src/cfclient/ui/toolboxes/ConsoleToolbox.py
@@ -20,25 +20,24 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 A detachable toolbox for showing console printouts from the Crazyflie
 """
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+from PyQt4.QtCore import Qt
 
-import sys
-
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal
+import cfclient
 
 __author__ = 'Bitcraze AB'
 __all__ = ['ConsoleToolbox']
 
 console_class = uic.loadUiType(
-    sys.path[0] + "/cfclient/ui/toolboxes/consoleToolbox.ui")[0]
+    cfclient.module_path + "/ui/toolboxes/consoleToolbox.ui")[0]
 
 
 class ConsoleToolbox(QtGui.QWidget, console_class):
diff --git a/src/cfclient/ui/toolboxes/CrtpSharkToolbox.py b/src/cfclient/ui/toolboxes/CrtpSharkToolbox.py
index 0941d8f294f7f1fcd3f6b200cb356969ab78acc2..fbbf0a03cae3379e55c3abfb35ca1fa461ac7b0f 100644
--- a/src/cfclient/ui/toolboxes/CrtpSharkToolbox.py
+++ b/src/cfclient/ui/toolboxes/CrtpSharkToolbox.py
@@ -20,28 +20,29 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 Toolbox for showing packets that is sent via the communication link when
 debugging.
 """
-
-import sys
 import os
-
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
 from time import time
 
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+from PyQt4.QtCore import pyqtSlot
+from PyQt4.QtCore import Qt
+
+import cfclient
+
 __author__ = 'Bitcraze AB'
-__all__ = ['CrtpSharkBoolbox']
+__all__ = ['CrtpSharkToolbox']
 
 param_tab_class = uic.loadUiType(
-    sys.path[0] + "/cfclient/ui/toolboxes/crtpSharkToolbox.ui")[0]
+    cfclient.module_path + "/ui/toolboxes/crtpSharkToolbox.ui")[0]
 
 
 class CrtpSharkToolbox(QtGui.QWidget, param_tab_class):
@@ -113,7 +114,7 @@ class CrtpSharkToolbox(QtGui.QWidget, param_tab_class):
         return Qt.RightDockWidgetArea
 
     def _save_data(self):
-        dir = os.path.join(sys.path[1], "logdata")
+        dir = os.path.join(cfclient.config_path, "logdata")
         fname = os.path.join(dir, "shark_data.csv")
         if not os.path.exists(dir):
             os.makedirs(dir)
diff --git a/src/cfclient/ui/toolboxes/DebugDriverToolbox.py b/src/cfclient/ui/toolboxes/DebugDriverToolbox.py
index b48174a30651dcaa1119cc61e6eef4a8c287ce7f..9a1185e3490494c713a994bcd443c6862ccc9ef9 100644
--- a/src/cfclient/ui/toolboxes/DebugDriverToolbox.py
+++ b/src/cfclient/ui/toolboxes/DebugDriverToolbox.py
@@ -20,31 +20,30 @@
 #  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.,
 #  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 Toolbox used to interact with the DebugDriver using a designated port. It's
 intended to be used for debugging.
 """
-
-import time
-import sys
-
 import struct
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL
+from cflib.crtp.crtpstack import CRTPPacket
+from cflib.crtp.crtpstack import CRTPPort
+from PyQt4 import QtGui
+from PyQt4 import uic
+from PyQt4.QtCore import pyqtSignal
+from PyQt4.QtCore import Qt
+
+import cfclient
 
 __author__ = 'Bitcraze AB'
 __all__ = ['DebugDriverToolbox']
 
 debugdriver_tab_class = uic.loadUiType(
-    sys.path[0] +
-    "/cfclient/ui/toolboxes/debugDriverToolbox.ui")[0]
+    cfclient.module_path +
+    "/ui/toolboxes/debugDriverToolbox.ui")[0]
 
 
 class DebugDriverToolbox(QtGui.QWidget, debugdriver_tab_class):
diff --git a/src/cfclient/ui/toolboxes/__init__.py b/src/cfclient/ui/toolboxes/__init__.py
index 1bf745c71202358824650c546ad567fd3fa8c580..5919562ab258c34efcea5075b980d845d1738b1e 100644
--- a/src/cfclient/ui/toolboxes/__init__.py
+++ b/src/cfclient/ui/toolboxes/__init__.py
@@ -31,28 +31,15 @@ List all the available toolboxes so they can be used by the UI.
 Dropping a new .py file into this directory will automatically list and load
 it into the UI when it is started.
 """
-
-import os
-import glob
-import logging
+from .ConsoleToolbox import ConsoleToolbox
+from .CrtpSharkToolbox import CrtpSharkToolbox
+from .DebugDriverToolbox import DebugDriverToolbox
 
 __author__ = 'Bitcraze AB'
 __all__ = []
 
-logger = logging.getLogger(__name__)
-
-foundToolboxes = [os.path.splitext(os.path.basename(f))[0] for f in
-                  glob.glob(os.path.dirname(__file__) +
-                            "/[A-Za-z]*Toolbox.py")]
-if len(foundToolboxes) == 0:
-    foundToolboxes = [os.path.splitext(os.path.basename(f))[0] for f in
-                      glob.glob(os.path.dirname(__file__) +
-                                "/[A-Za-z]*Toolbox.pyc")]
-
-logger.debug("Found toolboxes: %s", foundToolboxes)
-
-toolboxes = []
-
-for tb in foundToolboxes:
-    tbModule = __import__(tb, globals(), locals(), [tb], 1)
-    toolboxes.append(getattr(tbModule, tb))
+toolboxes = [
+    ConsoleToolbox,
+    CrtpSharkToolbox,
+    DebugDriverToolbox
+]
diff --git a/src/cfclient/ui/widgets/__init__.py b/src/cfclient/ui/widgets/__init__.py
index 532a061dbad4d4396822fbd8fac801ae2119aeb2..97dc2b09aa126593fdddc153621bce199891b153 100644
--- a/src/cfclient/ui/widgets/__init__.py
+++ b/src/cfclient/ui/widgets/__init__.py
@@ -28,3 +28,6 @@
 """
 Custom widgets used by the user interface.
 """
+
+# This is required to show an hidden import to py2exe
+from .hexspinbox import HexSpinBox as _HexSpinBox  # noqa
diff --git a/src/cfclient/ui/widgets/ai.py b/src/cfclient/ui/widgets/ai.py
index ffb27859b9c51560863d94006cd77018bab39eba..2bf317a851b0aa3ce3a22901dcac3940cd728ff3 100644
--- a/src/cfclient/ui/widgets/ai.py
+++ b/src/cfclient/ui/widgets/ai.py
@@ -254,9 +254,8 @@ if __name__ == "__main__":
             self.wid.repaint()
 
     def main():
-
         app = QtGui.QApplication(sys.argv)
-        ex = Example()
+        Example()
         sys.exit(app.exec_())
 
     if __name__ == '__main__':
diff --git a/src/cfclient/ui/widgets/hexspinbox.py b/src/cfclient/ui/widgets/hexspinbox.py
index 703867e88b20324869bca1e00c840a85366af963..d75b3957a65b88f7d1ced93a7a75793ec11a27bd 100644
--- a/src/cfclient/ui/widgets/hexspinbox.py
+++ b/src/cfclient/ui/widgets/hexspinbox.py
@@ -38,6 +38,7 @@ __all__ = ['HexSpinBox']
 
 
 class HexSpinBox(QAbstractSpinBox):
+
     def __init__(self, *args):
         QAbstractSpinBox.__init__(self, *args)
         regexp = QtCore.QRegExp('^0x[0-9A-Fa-f]{1,10}$')
diff --git a/src/cfclient/ui/widgets/plotwidget.py b/src/cfclient/ui/widgets/plotwidget.py
index 7c3cadc58e0ba40b5ba02befd57dffec35c3e410..774f85c04cebd828516c755e61a2fc6fc7fcfbb7 100644
--- a/src/cfclient/ui/widgets/plotwidget.py
+++ b/src/cfclient/ui/widgets/plotwidget.py
@@ -32,23 +32,18 @@ and manipulating the plot.
 For more advanced plotting save the data and use an external application.
 """
 
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, QLine, QPoint, \
-    QPointF, QSize, QRectF
+from PyQt4 import QtGui, uic
 
 from time import time
-import math
 
 import logging
 
-import sys
-
-from PyQt4 import Qt, QtCore, QtGui, uic
 from PyQt4.QtGui import QButtonGroup
-from PyQt4.QtCore import *
-from PyQt4.QtGui import *
-from PyQt4.Qt import *
-from time import time
+from PyQt4.QtCore import *  # noqa
+from PyQt4.QtGui import *  # noqa
+from PyQt4.Qt import *  # noqa
+
+import cfclient
 
 __author__ = 'Bitcraze AB'
 __all__ = ['PlotWidget']
@@ -56,15 +51,14 @@ __all__ = ['PlotWidget']
 logger = logging.getLogger(__name__)
 
 (plot_widget_class, connect_widget_base_class) = (
-    uic.loadUiType(sys.path[0] + '/cfclient/ui/widgets/plotter.ui'))
+    uic.loadUiType(cfclient.module_path + '/ui/widgets/plotter.ui'))
 
 # Try the imports for PyQtGraph to see if it is installed
 try:
     import pyqtgraph as pg
     from pyqtgraph import ViewBox
-    from pyqtgraph.Qt import QtCore, QtGui
-    import pyqtgraph.console
-    import numpy as np
+    import pyqtgraph.console  # noqa
+    import numpy as np  # noqa
 
     _pyqtgraph_found = True
 except Exception:
@@ -78,9 +72,9 @@ except Exception:
 # Windows. But for Linux this is not required and might not be installed with
 # the PyQtGraph package.
 try:
-    from scipy.stats import futil
-    from scipy.sparse.csgraph import _validation
-    from scipy.special import _ufuncs_cxx
+    from scipy.stats import futil  # noqa
+    from scipy.sparse.csgraph import _validation  # noqa
+    from scipy.special import _ufuncs_cxx  # noqa
 except Exception:
     pass
 
diff --git a/src/cfclient/utils/config.py b/src/cfclient/utils/config.py
index cbbe3ef2e460123e72e93a0f902e367a24095fa3..2bfe88af00037e1518de1f70f2ef051d97f13cd8 100644
--- a/src/cfclient/utils/config.py
+++ b/src/cfclient/utils/config.py
@@ -29,12 +29,12 @@
 """
 Gives access for reading and writing application configuration parameters
 """
-
-import sys
 import json
 import logging
 from .singleton import Singleton
 
+import cfclient
+
 __author__ = 'Bitcraze AB'
 __all__ = ['Config']
 
@@ -46,8 +46,8 @@ class Config(metaclass=Singleton):
 
     def __init__(self):
         """ Initializes the singleton and reads the config files """
-        self._dist_config = sys.path[0] + "/cfclient/configs/config.json"
-        self._config = sys.path[1] + "/config.json"
+        self._dist_config = cfclient.module_path + "/configs/config.json"
+        self._config = cfclient.config_path + "/config.json"
 
         [self._readonly, self._data] = self._read_distfile()
 
diff --git a/src/cfclient/utils/config_manager.py b/src/cfclient/utils/config_manager.py
index f92414054d8836ef3cd3ccb71c738e91945702ee..d2cc88cce0f050bb2fd7aad11f8ec1fe3198f393 100644
--- a/src/cfclient/utils/config_manager.py
+++ b/src/cfclient/utils/config_manager.py
@@ -31,7 +31,6 @@
 Manager for loading/accesing input device mappings.
 """
 
-import sys
 import json
 import logging
 import glob
@@ -41,6 +40,8 @@ import copy
 from .singleton import Singleton
 from cflib.utils.callbacks import Caller
 
+import cfclient
+
 __author__ = 'Bitcraze AB/Allyn Bauer'
 __all__ = ['ConfigManager']
 
@@ -50,7 +51,7 @@ logger = logging.getLogger(__name__)
 class ConfigManager(metaclass=Singleton):
     """ Singleton class for managing input processing """
     conf_needs_reload = Caller()
-    configs_dir = sys.path[1] + "/input"
+    configs_dir = cfclient.config_path + "/input"
 
     def __init__(self):
         """Initialize and create empty config list"""
diff --git a/src/cfclient/utils/input/__init__.py b/src/cfclient/utils/input/__init__.py
index ccb06c3262ddb3786dad9037d25dee95803da7ab..562472f798fbde4ea62a5d2e92343185ed2494b0 100644
--- a/src/cfclient/utils/input/__init__.py
+++ b/src/cfclient/utils/input/__init__.py
@@ -38,8 +38,6 @@ Windows drivers.
 The input device's axes and buttons are mapped to software inputs using a
 configuration file.
 """
-
-import sys
 import os
 import re
 import glob
@@ -50,13 +48,12 @@ import shutil
 from . import inputreaders as readers
 from . import inputinterfaces as interfaces
 
+import cfclient
 from cfclient.utils.config import Config
 from cfclient.utils.config_manager import ConfigManager
 
 from cfclient.utils.periodictimer import PeriodicTimer
 from cflib.utils.callbacks import Caller
-from . import mux
-from .mux import InputMux
 from .mux.nomux import NoMux
 from .mux.takeovermux import TakeOverMux
 from .mux.takeoverselectivemux import TakeOverSelectiveMux
@@ -144,7 +141,7 @@ class JoystickReader(object):
             os.makedirs(ConfigManager().configs_dir)
 
         for f in glob.glob(
-                sys.path[0] + "/cfclient/configs/input/[A-Za-z]*.json"):
+                cfclient.module_path + "/configs/input/[A-Za-z]*.json"):
             dest = os.path.join(ConfigManager().
                                 configs_dir, os.path.basename(f))
             if not os.path.isfile(dest):
diff --git a/src/cfclient/utils/input/inputinterfaces/__init__.py b/src/cfclient/utils/input/inputinterfaces/__init__.py
index 2947eb4b6c76f4270c6d55cd1204d7341e93b328..cf61c77ef7e50de42d210331d7b402b9c0a80120 100644
--- a/src/cfclient/utils/input/inputinterfaces/__init__.py
+++ b/src/cfclient/utils/input/inputinterfaces/__init__.py
@@ -75,6 +75,7 @@ def devices():
 
 
 class InputInterface(InputReaderInterface):
+
     def __init__(self, dev_name, dev_id, dev_reader):
         super(InputInterface, self).__init__(dev_name, dev_id, dev_reader)
 
diff --git a/src/cfclient/utils/input/inputinterfaces/leapmotion.py b/src/cfclient/utils/input/inputinterfaces/leapmotion.py
index 048e7e8c343940c698a2444f2d7640713be088ec..09b65dd947ed745488da4a6439e689307beb1f33 100644
--- a/src/cfclient/utils/input/inputinterfaces/leapmotion.py
+++ b/src/cfclient/utils/input/inputinterfaces/leapmotion.py
@@ -34,14 +34,11 @@ more info.
 
 try:
     import leapsdk.Leap as Leap
-    from leapsdk.Leap import CircleGesture, KeyTapGesture, ScreenTapGesture, \
-        SwipeGesture
 except Exception as e:
     raise Exception(
         "Leap Motion library probably not installed ({})".format(e))
 
 import logging
-import time
 
 __author__ = 'Bitcraze AB'
 __all__ = ['LeapmotionReader']
@@ -53,6 +50,7 @@ MODULE_NAME = "Leap Motion"
 
 
 class LeapListener(Leap.Listener):
+
     def set_data_callback(self, callback):
         self._dcb = callback
         self._nbr_of_fingers = 0
diff --git a/src/cfclient/utils/input/inputinterfaces/wiimote.py b/src/cfclient/utils/input/inputinterfaces/wiimote.py
index c9cdeec2f3b8f13ec44d40130295dec3cee94610..d0696009a067b25e0b15c49ec02312983c3e18b8 100644
--- a/src/cfclient/utils/input/inputinterfaces/wiimote.py
+++ b/src/cfclient/utils/input/inputinterfaces/wiimote.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 import logging
 from threading import Thread
 import time
@@ -20,6 +21,7 @@ class _Reader(object):
     # - limit_thrust
     # - limit_yaw
     # - open
+
     def devices(self):
         """List all the available connections"""
         raise NotImplemented()
@@ -53,6 +55,7 @@ PLUS = 4096
 
 
 class HandleWiimote(Thread):
+
     def __init__(self, reader, wii, *args):
         super(HandleWiimote, self).__init__(*args)
         self.reader = reader
diff --git a/src/cfclient/utils/input/inputinterfaces/zmqpull.py b/src/cfclient/utils/input/inputinterfaces/zmqpull.py
index 07cbae361fa1f59a147c4d47cc9da6c0a59805c5..66fe24dd8d39e55ebd2ff99851285454ca47f2b5 100644
--- a/src/cfclient/utils/input/inputinterfaces/zmqpull.py
+++ b/src/cfclient/utils/input/inputinterfaces/zmqpull.py
@@ -31,8 +31,6 @@ Input interface that supports receiving commands via ZMQ.
 """
 
 import logging
-import time
-import pprint
 from threading import Thread
 
 from cfclient.utils.config import Config
@@ -57,6 +55,7 @@ MODULE_NAME = "ZMQ"
 
 
 class _PullReader(Thread):
+
     def __init__(self, receiver, callback, *args):
         super(_PullReader, self).__init__(*args)
         self._receiver = receiver
diff --git a/src/cfclient/utils/input/inputreaderinterface.py b/src/cfclient/utils/input/inputreaderinterface.py
index 2f42d5c3f3ac4d80932a6b9e2d714854e94b4595..4857d51f02a0b9bc3088e0d51c7056ce0434b883 100644
--- a/src/cfclient/utils/input/inputreaderinterface.py
+++ b/src/cfclient/utils/input/inputreaderinterface.py
@@ -37,6 +37,7 @@ logger = logging.getLogger(__name__)
 
 
 class _ToggleState(dict):
+
     def __getattr__(self, attr):
         return self.get(attr)
 
@@ -45,6 +46,7 @@ class _ToggleState(dict):
 
 
 class InputData:
+
     def __init__(self):
         # self._toggled = {}
         self._axes = ("roll", "pitch", "yaw", "thrust")
@@ -95,6 +97,7 @@ class InputData:
 
 
 class InputReaderInterface(object):
+
     def __init__(self, dev_name, dev_id, dev_reader):
         """Initialize the reader"""
         # Set if the device supports mapping and can be configured
diff --git a/src/cfclient/utils/input/inputreaders/__init__.py b/src/cfclient/utils/input/inputreaders/__init__.py
index a5d5d15dd867dde1896fb99e1e71ff2ff3e08886..a60e1d1164be627838291cbb1f0e4fbd0d4b4ad7 100644
--- a/src/cfclient/utils/input/inputreaders/__init__.py
+++ b/src/cfclient/utils/input/inputreaders/__init__.py
@@ -78,6 +78,7 @@ def devices():
 
 
 class InputDevice(InputReaderInterface):
+
     def __init__(self, dev_name, dev_id, dev_reader):
         super(InputDevice, self).__init__(dev_name, dev_id, dev_reader)
 
diff --git a/src/cfclient/utils/input/inputreaders/linuxjsdev.py b/src/cfclient/utils/input/inputreaders/linuxjsdev.py
index 0e707e45e676768f9448dc060ba345a2e6b8f7a9..bbf9a1b7d988a5e5d6f366da060f2322413991e5 100644
--- a/src/cfclient/utils/input/inputreaders/linuxjsdev.py
+++ b/src/cfclient/utils/input/inputreaders/linuxjsdev.py
@@ -1,4 +1,4 @@
-# -*- coding: utf8 -*-
+# -*- coding: utf-8 -*-
 #     ||
 #  +------+      / __ )(_) /_______________ _____  ___
 #  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
@@ -22,20 +22,18 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
 """
 Linux joystick driver using the Linux input_joystick subsystem. Requires sysfs
 to be mounted on /sys and /dev/input/js* to be readable.
 
 This module is very linux specific but should work on any CPU platform
 """
-
-import sys
-import struct
-import glob
-import os
 import ctypes
+import glob
 import logging
+import os
+import struct
+import sys
 
 if not sys.platform.startswith('linux'):
     raise Exception("Only supported on Linux")
@@ -88,6 +86,7 @@ TYPE_AXIS = 2
 
 
 class _JS():
+
     def __init__(self, num, name):
         self.num = num
         self.name = name
diff --git a/src/cfclient/utils/input/inputreaders/pysdl2.py b/src/cfclient/utils/input/inputreaders/pysdl2.py
index 9ae86a94f04927531aa526d60bdd2d879fb7f932..a0e8c06a74c1b7a93890b358cecd01583e186138 100644
--- a/src/cfclient/utils/input/inputreaders/pysdl2.py
+++ b/src/cfclient/utils/input/inputreaders/pysdl2.py
@@ -20,22 +20,20 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
 #  USA.
-
 """
 Driver for reading data from the PySDL2 API. Used from Inpyt.py for reading
 input data.
 """
-
+import logging
 import sys
+import time
 from threading import Thread
+
 from queue import Queue
-import time
-import logging
 
 if sys.platform.startswith('linux'):
     raise Exception("No SDL2 support on Linux")
diff --git a/src/cfclient/utils/input/mux/__init__.py b/src/cfclient/utils/input/mux/__init__.py
index 68d8aae111fe9bf67b9ce346b9760a8e4b77fe45..48f9a473c8fed1c85e3f175ad50affdc5d7e0447 100644
--- a/src/cfclient/utils/input/mux/__init__.py
+++ b/src/cfclient/utils/input/mux/__init__.py
@@ -20,7 +20,6 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA
@@ -29,7 +28,6 @@
 The mux is used to open one or more devices and mix the inputs from all
 of them into one "input" for the Crazyflie and UI.
 """
-
 import logging
 
 __author__ = 'Bitcraze AB'
@@ -39,6 +37,7 @@ logger = logging.getLogger(__name__)
 
 
 class InputMux(object):
+
     def __init__(self, input_layer):
         self._devs = {"Device": None}
         self.name = "N/A"
diff --git a/src/cfclient/utils/input/mux/nomux.py b/src/cfclient/utils/input/mux/nomux.py
index 06059720928e4f11d3bfa76980e71615a5da5d90..ba4d51f05e5696d9c3f6934a54685c2c49069876 100644
--- a/src/cfclient/utils/input/mux/nomux.py
+++ b/src/cfclient/utils/input/mux/nomux.py
@@ -20,7 +20,6 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA
@@ -28,9 +27,9 @@
 """
 This mux will only use one device and not mix it with any other input.
 """
+import logging
 
 from . import InputMux
-import logging
 
 __author__ = 'Bitcraze AB'
 __all__ = ['NoMux']
@@ -39,6 +38,7 @@ logger = logging.getLogger(__name__)
 
 
 class NoMux(InputMux):
+
     def __init__(self, *args):
         super(NoMux, self).__init__(*args)
         self.name = "Normal"
diff --git a/src/cfclient/utils/input/mux/takeovermux.py b/src/cfclient/utils/input/mux/takeovermux.py
index 1816ffac7cfa65b66bda26073698dbff1159381a..b3aa6345a9e4d9abbd801320b44f38eba1ea2514 100644
--- a/src/cfclient/utils/input/mux/takeovermux.py
+++ b/src/cfclient/utils/input/mux/takeovermux.py
@@ -20,7 +20,6 @@
 #  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., 51 Franklin Street, Fifth Floor, Boston, MA
@@ -30,18 +29,18 @@ Mux for giving control to one device (slave/student) for all axis (roll/pitch/
 yaw/thrust) with the ability to take over all of them from a second device
 (master/teacher).
 """
-
 import logging
 
 from .takeoverselectivemux import TakeOverSelectiveMux
 
 __author__ = 'Bitcraze AB'
-__all__ = ['SelectiveMux']
+__all__ = ['TakeOverMux']
 
 logger = logging.getLogger(__name__)
 
 
 class TakeOverMux(TakeOverSelectiveMux):
+
     def __init__(self, *args):
         super(TakeOverMux, self).__init__(*args)
         self.name = "Teacher (RPYT)"
diff --git a/src/cfclient/utils/input/mux/takeoverselectivemux.py b/src/cfclient/utils/input/mux/takeoverselectivemux.py
index ed137e84aa24aee394185bfd4f81d392b16f9577..4531e8cb4deb068cc278dd04d55df16aafef41eb 100644
--- a/src/cfclient/utils/input/mux/takeoverselectivemux.py
+++ b/src/cfclient/utils/input/mux/takeoverselectivemux.py
@@ -42,6 +42,7 @@ logger = logging.getLogger(__name__)
 
 
 class TakeOverSelectiveMux(InputMux):
+
     def __init__(self, *args):
         super(TakeOverSelectiveMux, self).__init__(*args)
         self._master = "Teacher"
diff --git a/src/cfclient/utils/logconfigreader.py b/src/cfclient/utils/logconfigreader.py
index 36d539266053db1c173bbaf5ac2d06c5676f32e3..c548dcf4658a4db454851808e57fdc396a769b90 100644
--- a/src/cfclient/utils/logconfigreader.py
+++ b/src/cfclient/utils/logconfigreader.py
@@ -40,15 +40,12 @@ import json
 import logging
 import os
 import shutil
-import sys
-
-from PyQt4 import QtCore, QtGui, uic
-from PyQt4.QtCore import pyqtSlot, pyqtSignal
 
+import cfclient
 from cflib.crazyflie.log import LogVariable, LogConfig
 
 __author__ = 'Bitcraze AB'
-__all__ = ['LogVariable', 'LogConfigReader', 'LogConfigRemoveThis']
+__all__ = ['LogVariable', 'LogConfigReader']
 
 logger = logging.getLogger(__name__)
 
@@ -59,24 +56,25 @@ class LogConfigReader():
     def __init__(self, crazyflie):
         self.dsList = []
         # Check if user config exists, otherwise copy files
-        if (not os.path.exists(sys.path[1] + "/log")):
+        if (not os.path.exists(cfclient.config_path + "/log")):
             logger.info("No user config found, copying dist files")
-            os.makedirs(sys.path[1] + "/log")
+            os.makedirs(cfclient.config_path + "/log")
             for f in glob.glob(
-                    sys.path[0] + "/cfclient/configs/log/[A-Za-z]*.json"):
-                shutil.copy2(f, sys.path[1] + "/log")
+                    cfclient.module_path + "/configs/log/[A-Za-z]*.json"):
+                shutil.copy2(f, cfclient.config_path + "/log")
         self._cf = crazyflie
         self._cf.connected.add_callback(self._connected)
 
     def _read_config_files(self):
         """Read and parse log configurations"""
         configsfound = [os.path.basename(f) for f in
-                        glob.glob(sys.path[1] + "/log/[A-Za-z_-]*.json")]
+                        glob.glob(cfclient.config_path +
+                                  "/log/[A-Za-z_-]*.json")]
         new_dsList = []
         for conf in configsfound:
             try:
                 logger.info("Parsing [%s]", conf)
-                json_data = open(sys.path[1] + "/log/%s" % conf)
+                json_data = open(cfclient.config_path + "/log/%s" % conf)
                 self.data = json.load(json_data)
                 infoNode = self.data["logconfig"]["logblock"]
 
@@ -115,7 +113,7 @@ class LogConfigReader():
 
     def saveLogConfigFile(self, logconfig):
         """Save a log configuration to file"""
-        filename = sys.path[1] + "/log/" + logconfig.name + ".json"
+        filename = cfclient.config_path + "/log/" + logconfig.name + ".json"
         logger.info("Saving config for [%s]", filename)
 
         # Build tree for JSON
diff --git a/src/cfclient/utils/logdatawriter.py b/src/cfclient/utils/logdatawriter.py
index 3a7d365d30c2cedf313131c5ffb1cdb022d8bf7b..0f305fa19461dcb59794f2b1654140a0ce5ef1da 100644
--- a/src/cfclient/utils/logdatawriter.py
+++ b/src/cfclient/utils/logdatawriter.py
@@ -31,14 +31,11 @@ Used to write log data to files.
 """
 
 import os
-import sys
 import datetime
 
 import logging
 
-from cflib.crazyflie.log import LogConfig
-
-import traceback
+import cfclient
 
 __author__ = 'Bitcraze AB'
 __all__ = ['LogWriter']
@@ -55,7 +52,7 @@ class LogWriter():
         self._dir = directory
         self._connected_ts = connected_ts
 
-        self._dir = os.path.join(sys.path[1], "logdata",
+        self._dir = os.path.join(cfclient.config_path, "logdata",
                                  connected_ts.strftime("%Y%m%dT%H-%M-%S"))
         self._file = None
         self._header_written = False
diff --git a/src/cfclient/utils/periodictimer.py b/src/cfclient/utils/periodictimer.py
index bb889113d35182695db0a4dca2beca9d61b33142..7ba3063d63a34b6f880feb0ee8c89863839c6957 100644
--- a/src/cfclient/utils/periodictimer.py
+++ b/src/cfclient/utils/periodictimer.py
@@ -68,6 +68,7 @@ class PeriodicTimer:
 
 
 class _PeriodicTimerThread(Thread):
+
     def __init__(self, period, caller):
         super(_PeriodicTimerThread, self).__init__()
         self._period = period
diff --git a/src/cfclient/utils/zmq_led_driver.py b/src/cfclient/utils/zmq_led_driver.py
index 79632836508513f83672f3dc27dfd76bd7e8dff8..e639b0921c4aea26e88a7075c0d39cd35549333b 100644
--- a/src/cfclient/utils/zmq_led_driver.py
+++ b/src/cfclient/utils/zmq_led_driver.py
@@ -30,8 +30,6 @@
 Give access to the LED driver memory via ZMQ.
 """
 
-import cflib
-import cflib.crazyflie
 from cflib.crazyflie.mem import MemoryElement
 
 import logging
diff --git a/src/cfclient/utils/zmq_param.py b/src/cfclient/utils/zmq_param.py
index 16b105632442100d5062fda700f36eaa3d792b6a..da221b6bebfd9f818ebcb4e6a67f1aa4160f4ab8 100644
--- a/src/cfclient/utils/zmq_param.py
+++ b/src/cfclient/utils/zmq_param.py
@@ -47,6 +47,7 @@ except Exception as e:
 
 
 class _PullReader(Thread):
+
     def __init__(self, receiver, callback, *args):
         super(_PullReader, self).__init__(*args)
         self._receiver = receiver
@@ -89,7 +90,7 @@ class ZMQParamAccess:
             self._receiver.send_json(response)
             self._receiver_thread.lock.release()
         if data["cmd"] == "set":
-            resp = {"version": 1}
+            resp = {"version": 1}  # noqa
             group = data["name"].split(".")[0]
             name = data["name"].split(".")[1]
             self._cf.param.add_update_callback(group=group, name=name,
diff --git a/src/cflib/cflib/__init__.py b/src/cflib/cflib/__init__.py
deleted file mode 100644
index 536acc1111695aade66f938f03689f8a10d71d4c..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/__init__.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-The Crazyflie Micro Quadcopter library API used to communicate with the
-Crazyflie Micro Quadcopter via a communication link.
-
-The API takes care of scanning, opening and closing the communication link
-as well as sending/receiving data from the Crazyflie.
-
-A link is described using an URI of the following format:
-    <interface>://<interface defined data>.
-See each link for the data that can be included in the URI for that interface.
-
-The two main uses-cases are scanning for Crazyflies available on a
-communication link and opening a communication link to a Crazyflie.
-
-Example of scanning for available Crazyflies on all communication links:
-cflib.crtp.init_drivers()
-available = cflib.crtp.scan_interfaces()
-for i in available:
-    print "Found Crazyflie on URI [%s] with comment [%s]"
-            % (available[0], available[1])
-
-Example of connecting to a Crazyflie with know URI (radio dongle 0 and
-radio channel 125):
-cf = Crazyflie()
-cf.open_link("radio://0/125")
-...
-cf.close_link()
-"""
diff --git a/src/cflib/cflib/bootloader/__init__.py b/src/cflib/cflib/bootloader/__init__.py
deleted file mode 100644
index 4e6bec5ca53592c658692e144dd7035a6e7c9c98..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/bootloader/__init__.py
+++ /dev/null
@@ -1,388 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Bootloading utilities for the Crazyflie.
-"""
-
-from cflib.utils.callbacks import Caller
-from .cloader import Cloader
-from .boottypes import BootVersion, TargetTypes, Target
-import zipfile
-import json
-import sys
-import time
-import logging
-
-logger = logging.getLogger(__name__)
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Bootloader']
-
-
-class Bootloader:
-    """Bootloader utility for the Crazyflie"""
-
-    def __init__(self, clink=None):
-        """Init the communication class by starting to communicate with the
-        link given. clink is the link address used after resetting to the
-        bootloader.
-
-        The device is actually considered in firmware mode.
-        """
-        self.clink = clink
-        self.in_loader = False
-
-        self.page_size = 0
-        self.buffer_pages = 0
-        self.flash_pages = 0
-        self.start_page = 0
-        self.cpuid = "N/A"
-        self.error_code = 0
-        self.protocol_version = 0
-
-        # Outgoing callbacks for progress
-        # int
-        self.progress_cb = None
-        # msg
-        self.error_cb = None
-        # bool
-        self.in_bootloader_cb = None
-        # Target
-        self.dev_info_cb = None
-
-        # self.dev_info_cb.add_callback(self._dev_info)
-        # self.in_bootloader_cb.add_callback(self._bootloader_info)
-
-        self._boot_plat = None
-
-        self._cload = Cloader(clink,
-                              info_cb=self.dev_info_cb,
-                              in_boot_cb=self.in_bootloader_cb)
-
-    def start_bootloader(self, warm_boot=False):
-        if warm_boot:
-            self._cload.open_bootloader_uri(self.clink)
-            started = self._cload.reset_to_bootloader(TargetTypes.NRF51)
-            if started:
-                started = self._cload.check_link_and_get_info()
-        else:
-            uri = self._cload.scan_for_bootloader()
-
-            # Workaround for libusb on Windows (open/close too fast)
-            time.sleep(1)
-
-            if uri:
-                self._cload.open_bootloader_uri(uri)
-                started = self._cload.check_link_and_get_info()
-            else:
-                started = False
-
-        if started:
-            self.protocol_version = self._cload.protocol_version
-
-            if (self.protocol_version == BootVersion.CF1_PROTO_VER_0 or
-                    self.protocol_version == BootVersion.CF1_PROTO_VER_1):
-                # Nothing more to do
-                pass
-            elif self.protocol_version == BootVersion.CF2_PROTO_VER:
-                self._cload.request_info_update(TargetTypes.NRF51)
-            else:
-                print("Bootloader protocol 0x{:X} not "
-                      "supported!".self.protocol_version)
-
-        return started
-
-    def get_target(self, target_id):
-        return self._cload.request_info_update(target_id)
-
-    def read_cf1_config(self):
-        """Read a flash page from the specified target"""
-        target = self._cload.targets[0xFF]
-        config_page = target.flash_pages - 1
-
-        return self._cload.read_flash(addr=0xFF, page=config_page)
-
-    def write_cf1_config(self, data):
-        target = self._cload.targets[0xFF]
-        config_page = target.flash_pages - 1
-
-        to_flash = {"target": target, "data": data, "type": "CF1 config",
-                    "start_page": config_page}
-
-        self._internal_flash(target=to_flash)
-
-    def flash(self, filename, targets):
-        for target in targets:
-            if TargetTypes.from_string(target) not in self._cload.targets:
-                print("Target {} not found by bootloader".format(target))
-                return False
-
-        files_to_flash = ()
-        if zipfile.is_zipfile(filename):
-            # Read the manifest (don't forget to check so there is one!)
-            try:
-                zf = zipfile.ZipFile(filename)
-                js = zf.read("manifest.json").decode("UTF-8")
-                j = json.loads(js)
-                files = j["files"]
-                platform_id = self._get_platform_id()
-                files_for_platform = self._filter_platform(files, platform_id)
-                if len(targets) == 0:
-                    targets = self._extract_targets_from_manifest_files(
-                        files_for_platform)
-
-                zip_targets = self._extract_zip_targets(files_for_platform)
-            except KeyError as e:
-                print(e)
-                print("No manifest.json in {}".format(filename))
-                return
-
-            try:
-                # Match and create targets
-                for target in targets:
-                    t = targets[target]
-                    for type in t:
-                        file_to_flash = {}
-                        current_target = "{}-{}".format(target, type)
-                        file_to_flash["type"] = type
-                        # Read the data, if this fails we bail
-                        file_to_flash["target"] = self._cload.targets[
-                            TargetTypes.from_string(target)]
-                        file_to_flash["data"] = zf.read(
-                            zip_targets[target][type]["filename"])
-                        file_to_flash["start_page"] = file_to_flash[
-                            "target"].start_page
-                        files_to_flash += (file_to_flash,)
-            except KeyError as e:
-                print("Could not find a file for {} in {}".format(
-                    current_target, filename))
-                return False
-
-        else:
-            if len(targets) != 1:
-                print("Not an archive, must supply one target to flash")
-            else:
-                file_to_flash = {}
-                file_to_flash["type"] = "binary"
-                f = open(filename, 'rb')
-                for t in targets:
-                    file_to_flash["target"] = self._cload.targets[
-                        TargetTypes.from_string(t)]
-                    file_to_flash["type"] = targets[t][0]
-                    file_to_flash["start_page"] = file_to_flash[
-                        "target"].start_page
-                file_to_flash["data"] = f.read()
-                f.close()
-                files_to_flash += (file_to_flash,)
-
-        if not self.progress_cb:
-            print("")
-
-        file_counter = 0
-        for target in files_to_flash:
-            file_counter += 1
-            self._internal_flash(target, file_counter, len(files_to_flash))
-
-    def _filter_platform(self, files, platform_id):
-        result = {}
-        for file in files:
-            file_info = files[file]
-            file_platform = file_info["platform"]
-            if platform_id == file_platform:
-                result[file] = file_info
-        return result
-
-    def _extract_zip_targets(self, files):
-        zip_targets = {}
-        for file in files:
-            file_name = file
-            file_info = files[file]
-            file_target = file_info["target"]
-            file_type = file_info["type"]
-            if file_target not in zip_targets:
-                zip_targets[file_target] = {}
-            zip_targets[file_target][file_type] = {
-                "filename": file_name}
-        return zip_targets
-
-    def _extract_targets_from_manifest_files(self, files):
-        targets = {}
-        for file in files:
-            file_info = files[file]
-            file_target = file_info["target"]
-            file_type = file_info["type"]
-            if file_target in targets:
-                targets[file_target] += (file_type,)
-            else:
-                targets[file_target] = (file_type,)
-
-        return targets
-
-    def reset_to_firmware(self):
-        if self._cload.protocol_version == BootVersion.CF2_PROTO_VER:
-            self._cload.reset_to_firmware(TargetTypes.NRF51)
-        else:
-            self._cload.reset_to_firmware(TargetTypes.STM32)
-
-    def close(self):
-        if self._cload:
-            self._cload.close()
-
-    def _internal_flash(self, target, current_file_number=1, total_files=1):
-
-        image = target["data"]
-        t_data = target["target"]
-
-        start_page = target["start_page"]
-
-        # If used from a UI we need some extra things for reporting progress
-        factor = (100.0 * t_data.page_size) / len(image)
-        progress = 0
-
-        if self.progress_cb:
-            self.progress_cb(
-                "({}/{}) Starting...".format(current_file_number, total_files),
-                int(progress))
-        else:
-            sys.stdout.write(
-                "Flashing {} of {} to {} ({}): ".format(
-                    current_file_number, total_files,
-                    TargetTypes.to_string(t_data.id), target["type"]))
-            sys.stdout.flush()
-
-        if len(image) > ((t_data.flash_pages - start_page) *
-                         t_data.page_size):
-            if self.progress_cb:
-                self.progress_cb(
-                    "Error: Not enough space to flash the image file.",
-                    int(progress))
-            else:
-                print("Error: Not enough space to flash the image file.")
-            raise Exception()
-
-        if not self.progress_cb:
-            logger.info(("%d bytes (%d pages) " % (
-                (len(image) - 1), int(len(image) / t_data.page_size) + 1)))
-            sys.stdout.write(("%d bytes (%d pages) " % (
-                (len(image) - 1), int(len(image) / t_data.page_size) + 1)))
-            sys.stdout.flush()
-
-        # For each page
-        ctr = 0  # Buffer counter
-        for i in range(0, int((len(image) - 1) / t_data.page_size) + 1):
-            # Load the buffer
-            if ((i + 1) * t_data.page_size) > len(image):
-                self._cload.upload_buffer(
-                    t_data.addr, ctr, 0, image[i * t_data.page_size:])
-            else:
-                self._cload.upload_buffer(
-                    t_data.addr, ctr, 0,
-                    image[i * t_data.page_size: (i + 1) * t_data.page_size])
-
-            ctr += 1
-
-            if self.progress_cb:
-                progress += factor
-                self.progress_cb("({}/{}) Uploading buffer to {}...".format(
-                    current_file_number,
-                    total_files,
-                    TargetTypes.to_string(t_data.id)),
-
-                    int(progress))
-            else:
-                sys.stdout.write(".")
-                sys.stdout.flush()
-
-            # Flash when the complete buffers are full
-            if ctr >= t_data.buffer_pages:
-                if self.progress_cb:
-                    self.progress_cb("({}/{}) Writing buffer to {}...".format(
-                        current_file_number,
-                        total_files,
-                        TargetTypes.to_string(t_data.id)),
-
-                        int(progress))
-                else:
-                    sys.stdout.write("%d" % ctr)
-                    sys.stdout.flush()
-                if not self._cload.write_flash(t_data.addr, 0,
-                                               start_page + i - (ctr - 1),
-                                               ctr):
-                    if self.progress_cb:
-                        self.progress_cb(
-                            "Error during flash operation (code %d)".format(
-                                self._cload.error_code),
-                            int(progress))
-                    else:
-                        print("\nError during flash operation (code %d). "
-                              "Maybe wrong radio link?" %
-                              self._cload.error_code)
-                    raise Exception()
-
-                ctr = 0
-
-        if ctr > 0:
-            if self.progress_cb:
-                self.progress_cb("({}/{}) Writing buffer to {}...".format(
-                    current_file_number,
-                    total_files,
-                    TargetTypes.to_string(t_data.id)),
-                    int(progress))
-            else:
-                sys.stdout.write("%d" % ctr)
-                sys.stdout.flush()
-            if not self._cload.write_flash(
-                    t_data.addr, 0,
-                    (start_page + (int((len(image) - 1) / t_data.page_size)) -
-                     (ctr - 1)), ctr):
-                if self.progress_cb:
-                    self.progress_cb(
-                        "Error during flash operation (code %d)".format(
-                            self._cload.error_code),
-                        int(progress))
-                else:
-                    print("\nError during flash operation (code %d). Maybe"
-                          " wrong radio link?" % self._cload.error_code)
-                raise Exception()
-
-        if self.progress_cb:
-            self.progress_cb(
-                "({}/{}) Flashing done!".format(current_file_number,
-                                                total_files),
-                int(100))
-        else:
-            print("")
-
-    def _get_platform_id(self):
-        """Get platform identifier used in the zip manifest for curr copter"""
-        identifier = "cf1"
-        if (BootVersion.is_cf2(self.protocol_version)):
-            identifier = "cf2"
-
-        return identifier
diff --git a/src/cflib/cflib/bootloader/boottypes.py b/src/cflib/cflib/bootloader/boottypes.py
deleted file mode 100644
index b637e98abfe1c16d62b0186d3e28ffb90a57ae34..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/bootloader/boottypes.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Bootloading utilities for the Crazyflie.
-"""
-
-__author__ = 'Bitcraze AB'
-__all__ = ['BootVersion', 'TargetTypes', 'Target']
-
-
-class BootVersion:
-    CF1_PROTO_VER_0 = 0x00
-    CF1_PROTO_VER_1 = 0x01
-    CF2_PROTO_VER = 0x10
-
-    @staticmethod
-    def to_ver_string(ver):
-        if (ver == BootVersion.CF1_PROTO_VER_0 or ver == BootVersion.
-                CF1_PROTO_VER_1):
-            return "Crazyflie Nano Quadcopter (1.0)"
-        if ver == BootVersion.CF2_PROTO_VER:
-            return "Crazyflie 2.0"
-        return "Unknown"
-
-    @staticmethod
-    def is_cf2(ver):
-        return ver == BootVersion.CF2_PROTO_VER
-
-
-class TargetTypes:
-    STM32 = 0xFF
-    NRF51 = 0xFE
-
-    @staticmethod
-    def to_string(target):
-        if target == TargetTypes.STM32:
-            return "stm32"
-        if target == TargetTypes.NRF51:
-            return "nrf51"
-        return "Unknown"
-
-    @staticmethod
-    def from_string(name):
-        if name == "stm32":
-            return TargetTypes.STM32
-        if name == "nrf51":
-            return TargetTypes.NRF51
-        return 0
-
-
-class Target:
-    def __init__(self, id):
-        self.id = id
-        self.protocol_version = 0xFF
-        self.page_size = 0
-        self.buffer_pages = 0
-        self.flash_pages = 0
-        self.start_page = 0
-        self.cpuid = ""
-        self.data = None
-
-    def __str__(self):
-        ret = ""
-        ret += "Target info: {} (0x{:X})\n".format(
-            TargetTypes.to_string(self.id), self.id)
-        ret += "Flash pages: %d | Page size: %d | Buffer pages: %d |" \
-               " Start page: %d\n" % (self.flash_pages, self.page_size,
-                                      self.buffer_pages, self.start_page)
-        ret += "%d KBytes of flash available for firmware image." % (
-            (self.flash_pages - self.start_page) * self.page_size / 1024)
-        return ret
diff --git a/src/cflib/cflib/bootloader/cloader.py b/src/cflib/cflib/bootloader/cloader.py
deleted file mode 100644
index 1bffeb15bfd1b741f8960920deb587550ec9ff73..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/bootloader/cloader.py
+++ /dev/null
@@ -1,423 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Crazyflie radio bootloader for flashing firmware.
-"""
-
-import logging
-
-import time
-import struct
-import math
-import random
-
-import cflib.crtp
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
-
-from .boottypes import TargetTypes, Target
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Cloader']
-
-logger = logging.getLogger(__name__)
-
-
-class Cloader:
-    """Bootloader utility for the Crazyflie"""
-
-    def __init__(self, link, info_cb=None, in_boot_cb=None):
-        """Init the communication class by starting to communicate with the
-        link given. clink is the link address used after resetting to the
-        bootloader.
-
-        The device is actually considered in firmware mode.
-        """
-        self.link = None
-        self.uri = link
-        self.in_loader = False
-
-        self.page_size = 0
-        self.buffer_pages = 0
-        self.flash_pages = 0
-        self.start_page = 0
-        self.cpuid = "N/A"
-        self.error_code = 0
-        self.protocol_version = 0xFF
-
-        self._info_cb = info_cb
-        self._in_boot_cb = in_boot_cb
-
-        self.targets = {}
-        self.mapping = None
-        self._available_boot_uri = ("radio://0/110/2M", "radio://0/0/2M")
-
-    def close(self):
-        """ Close the link """
-        if self.link:
-            self.link.close()
-
-    def scan_for_bootloader(self):
-        link = cflib.crtp.get_link_driver("radio://0")
-        ts = time.time()
-        res = ()
-        while len(res) == 0 and (time.time() - ts) < 10:
-            res = link.scan_selected(self._available_boot_uri)
-
-        link.close()
-
-        if len(res) > 0:
-            return res[0]
-        return None
-
-    def reset_to_bootloader(self, target_id):
-        retry_counter = 5
-        pk = CRTPPacket()
-        pk.set_header(0xFF, 0xFF)
-        pk.data = (target_id, 0xFF)
-        self.link.send_packet(pk)
-
-        pk = self.link.receive_packet(1)
-
-        while ((not pk or pk.header != 0xFF or
-                struct.unpack("<BB", pk.data[0:2]) != (target_id, 0xFF)
-                ) and retry_counter >= 0):
-            pk = self.link.receive_packet(1)
-            retry_counter -= 1
-
-        if pk:
-            new_address = (0xb1,) + struct.unpack("<BBBB", pk.data[2:6][::-1])
-
-            pk = CRTPPacket()
-            pk.set_header(0xFF, 0xFF)
-            pk.data = (target_id, 0xF0, 0x00)
-            self.link.send_packet(pk)
-
-            addr = int(struct.pack("B" * 5, *new_address).encode('hex'), 16)
-
-            time.sleep(0.2)
-            self.link.close()
-            time.sleep(0.2)
-            self.link = cflib.crtp.get_link_driver(
-                "radio://0/0/2M/{}".format(addr))
-
-            return True
-        else:
-            return False
-
-    def reset_to_bootloader1(self, cpu_id):
-        """ Reset to the bootloader
-        The parameter cpuid shall correspond to the device to reset.
-
-        Return true if the reset has been done and the contact with the
-        bootloader is established.
-        """
-        # Send an echo request and wait for the answer
-        # Mainly aim to bypass a bug of the crazyflie firmware that prevents
-        # reset before normal CRTP communication
-        pk = CRTPPacket()
-        pk.port = CRTPPort.LINKCTRL
-        pk.data = (1, 2, 3) + cpu_id
-        self.link.send_packet(pk)
-
-        pk = None
-        while True:
-            pk = self.link.receive_packet(2)
-            if not pk:
-                return False
-
-            if pk.port == CRTPPort.LINKCTRL:
-                break
-
-        # Send the reset to bootloader request
-        pk = CRTPPacket()
-        pk.set_header(0xFF, 0xFF)
-        pk.data = (0xFF, 0xFE) + cpu_id
-        self.link.send_packet(pk)
-
-        # Wait to ack the reset ...
-        pk = None
-        while True:
-            pk = self.link.receive_packet(2)
-            if not pk:
-                return False
-
-            if pk.port == 0xFF and tuple(pk.data) == (0xFF, 0xFE) + cpu_id:
-                pk.data = (0xFF, 0xF0) + cpu_id
-                self.link.send_packet(pk)
-                break
-
-        time.sleep(0.1)
-        self.link.close()
-        self.link = cflib.crtp.get_link_driver(self.clink_address)
-        # time.sleep(0.1)
-
-        return self._update_info()
-
-    def reset_to_firmware(self, target_id):
-        """ Reset to firmware
-        The parameter cpuid shall correspond to the device to reset.
-
-        Return true if the reset has been done
-        """
-        # The fake CPU ID is legacy from the Crazyflie 1.0
-        # In order to reset the CPU id had to be sent, but this
-        # was removed before launching it. But the length check is
-        # still in the bootloader. So to work around this bug so
-        # some extra data needs to be sent.
-        fake_cpu_id = (1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12)
-        # Send the reset to bootloader request
-        pk = CRTPPacket()
-        pk.set_header(0xFF, 0xFF)
-        pk.data = (target_id, 0xFF) + fake_cpu_id
-        self.link.send_packet(pk)
-
-        # Wait to ack the reset ...
-        pk = None
-        while True:
-            pk = self.link.receive_packet(2)
-            if not pk:
-                return False
-
-            if (pk.header == 0xFF and struct.unpack(
-                    "B" * len(pk.data), pk.data)[:2] == (target_id, 0xFF)):
-                # Difference in CF1 and CF2 (CPU ID)
-                if target_id == 0xFE:
-                    pk.data = (target_id, 0xF0, 0x01)
-                else:
-                    pk.data = (target_id, 0xF0) + fake_cpu_id
-                self.link.send_packet(pk)
-                break
-
-        time.sleep(0.1)
-
-    def open_bootloader_uri(self, uri=None):
-        if self.link:
-            self.link.close()
-        if uri:
-            self.link = cflib.crtp.get_link_driver(uri)
-        else:
-            self.link = cflib.crtp.get_link_driver(self.clink_address)
-
-    def check_link_and_get_info(self, target_id=0xFF):
-        """Try to get a connection with the bootloader by requesting info
-        5 times. This let roughly 10 seconds to boot the copter ..."""
-        for _ in range(0, 5):
-            if self._update_info(target_id):
-                if self._in_boot_cb:
-                    self._in_boot_cb.call(True, self.targets[
-                        target_id].protocol_version)
-                if self._info_cb:
-                    self._info_cb.call(self.targets[target_id])
-                if self.protocol_version != 1:
-                    return True
-                # Set radio link to a random address
-                addr = [0xbc] + [random.randint(0, 255) for x in range(4)]
-                return self._set_address(addr)
-        return False
-
-    def _set_address(self, new_address):
-        """ Change copter radio address.
-            This function works only with crazyradio CRTP link.
-        """
-
-        logging.debug("Setting bootloader radio address to"
-                      " {}".format(new_address))
-
-        if len(new_address) != 5:
-            raise Exception("Radio address should be 5 bytes long")
-
-        self.link.pause()
-
-        for _ in range(10):
-            logging.debug("Trying to set new radio address")
-            self.link.cradio.set_address((0xE7,) * 5)
-            pkdata = (0xFF, 0xFF, 0x11) + tuple(new_address)
-            self.link.cradio.send_packet(pkdata)
-            self.link.cradio.set_address(tuple(new_address))
-            if self.link.cradio.send_packet((0xff,)).ack:
-                logging.info("Bootloader set to radio address"
-                             " {}".format(new_address))
-                self.link.restart()
-                return True
-
-        self.link.restart()
-        return False
-
-    def request_info_update(self, target_id):
-        if target_id not in self.targets:
-            self._update_info(target_id)
-        if self._info_cb:
-            self._info_cb.call(self.targets[target_id])
-        return self.targets[target_id]
-
-    def _update_info(self, target_id):
-        """ Call the command getInfo and fill up the information received in
-        the fields of the object
-        """
-
-        # Call getInfo ...
-        pk = CRTPPacket()
-        pk.set_header(0xFF, 0xFF)
-        pk.data = (target_id, 0x10)
-        self.link.send_packet(pk)
-
-        # Wait for the answer
-        pk = self.link.receive_packet(2)
-
-        if (pk and pk.header == 0xFF and struct.unpack("<BB", pk.data[0:2]) ==
-                (target_id, 0x10)):
-            tab = struct.unpack("BBHHHH", pk.data[0:10])
-            cpuid = struct.unpack("B" * 12, pk.data[10:22])
-            if target_id not in self.targets:
-                self.targets[target_id] = Target(target_id)
-            self.targets[target_id].addr = target_id
-            if len(pk.data) > 22:
-                self.targets[target_id].protocol_version = pk.datat[22]
-                self.protocol_version = pk.datat[22]
-            self.targets[target_id].page_size = tab[2]
-            self.targets[target_id].buffer_pages = tab[3]
-            self.targets[target_id].flash_pages = tab[4]
-            self.targets[target_id].start_page = tab[5]
-            self.targets[target_id].cpuid = "%02X" % cpuid[0]
-            for i in cpuid[1:]:
-                self.targets[target_id].cpuid += ":%02X" % i
-
-            if (self.protocol_version == 0x10 and
-                    target_id == TargetTypes.STM32):
-                self._update_mapping(target_id)
-
-            return True
-
-        return False
-
-    def _update_mapping(self, target_id):
-        pk = CRTPPacket()
-        pk.set_header(0xff, 0xff)
-        pk.data = (target_id, 0x12)
-        self.link.send_packet(pk)
-
-        pk = self.link.receive_packet(2)
-
-        if (pk and pk.header == 0xFF and struct.unpack("<BB", pk.data[0:2]) ==
-                (target_id, 0x12)):
-            m = pk.datat[2:]
-
-            if (len(m) % 2) != 0:
-                raise Exception("Malformed flash mapping packet")
-
-            self.mapping = []
-            page = 0
-            for i in range(int(len(m) / 2)):
-                for j in range(m[2 * i]):
-                    self.mapping.append(page)
-                    page += m[(2 * i) + 1]
-
-    def upload_buffer(self, target_id, page, address, buff):
-        """Upload data into a buffer on the Crazyflie"""
-        # print len(buff)
-        count = 0
-        pk = CRTPPacket()
-        pk.set_header(0xFF, 0xFF)
-        pk.data = struct.pack("=BBHH", target_id, 0x14, page, address)
-
-        for i in range(0, len(buff)):
-            pk.data.append(buff[i])
-
-            count += 1
-
-            if count > 24:
-                self.link.send_packet(pk)
-                count = 0
-                pk = CRTPPacket()
-                pk.set_header(0xFF, 0xFF)
-                pk.data = struct.pack("=BBHH", target_id, 0x14, page,
-                                      i + address + 1)
-
-        self.link.send_packet(pk)
-
-    def read_flash(self, addr=0xFF, page=0x00):
-        """Read back a flash page from the Crazyflie and return it"""
-        buff = bytearray()
-
-        page_size = self.targets[addr].page_size
-
-        for i in range(0, int(math.ceil(page_size / 25.0))):
-            pk = None
-            retry_counter = 5
-            while ((not pk or pk.header != 0xFF or
-                    struct.unpack("<BB", pk.data[0:2]) != (addr, 0x1C)) and
-                    retry_counter >= 0):
-                pk = CRTPPacket()
-                pk.set_header(0xFF, 0xFF)
-                pk.data = struct.pack("<BBHH", addr, 0x1C, page, (i * 25))
-                self.link.send_packet(pk)
-
-                pk = self.link.receive_packet(1)
-                retry_counter -= 1
-            if (retry_counter < 0):
-                return None
-            else:
-                buff += pk.data[6:]
-
-        # For some reason we get one byte extra here...
-        return buff[0:page_size]
-
-    def write_flash(self, addr, page_buffer, target_page, page_count):
-        """Initiate flashing of data in the buffer to flash."""
-        # print "Write page", flashPage
-        # print "Writing page [%d] and [%d] forward" % (flashPage, nPage)
-        pk = None
-        retry_counter = 5
-        # print "Flasing to 0x{:X}".format(addr)
-        while ((not pk or pk.header != 0xFF or
-                struct.unpack("<BB", pk.data[0:2]) != (addr, 0x18)) and
-               retry_counter >= 0):
-            pk = CRTPPacket()
-            pk.set_header(0xFF, 0xFF)
-            pk.data = struct.pack("<BBHHH", addr, 0x18, page_buffer,
-                                  target_page, page_count)
-            self.link.send_packet(pk)
-            pk = self.link.receive_packet(1)
-            retry_counter -= 1
-
-        if retry_counter < 0:
-            self.error_code = -1
-            return False
-
-        self.error_code = pk.data[3]
-
-        return pk.data[2] == 1
-
-    def decode_cpu_id(self, cpuid):
-        """Decode the CPU id into a string"""
-        ret = ()
-        for i in cpuid.split(':'):
-            ret += (eval("0x" + i),)
-
-        return ret
diff --git a/src/cflib/cflib/cache/27A2C4BA.json b/src/cflib/cflib/cache/27A2C4BA.json
deleted file mode 100644
index b71d9c655880540900b4577694ccadb68934003a..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/cache/27A2C4BA.json
+++ /dev/null
@@ -1,257 +0,0 @@
-{
-  "sensorfusion6": {
-    "ki": {
-      "ident": 24, 
-      "group": "sensorfusion6", 
-      "name": "ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kp": {
-      "ident": 23, 
-      "group": "sensorfusion6", 
-      "name": "kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "cpu": {
-    "flash": {
-      "ident": 1, 
-      "group": "cpu", 
-      "name": "flash", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "id2": {
-      "ident": 4, 
-      "group": "cpu", 
-      "name": "id2", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 0
-    }, 
-    "id0": {
-      "ident": 2, 
-      "group": "cpu", 
-      "name": "id0", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 0
-    }, 
-    "id1": {
-      "ident": 3, 
-      "group": "cpu", 
-      "name": "id1", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 0
-    }
-  }, 
-  "version": {
-    "revision0": {
-      "ident": 25, 
-      "group": "version", 
-      "name": "revision0", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 0
-    }, 
-    "revision1": {
-      "ident": 26, 
-      "group": "version", 
-      "name": "revision1", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }
-  }, 
-  "pid_rate": {
-    "yaw_kp": {
-      "ident": 11, 
-      "group": "pid_rate", 
-      "name": "yaw_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kd": {
-      "ident": 7, 
-      "group": "pid_rate", 
-      "name": "roll_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kp": {
-      "ident": 8, 
-      "group": "pid_rate", 
-      "name": "pitch_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_ki": {
-      "ident": 6, 
-      "group": "pid_rate", 
-      "name": "roll_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_ki": {
-      "ident": 9, 
-      "group": "pid_rate", 
-      "name": "pitch_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kp": {
-      "ident": 5, 
-      "group": "pid_rate", 
-      "name": "roll_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_kd": {
-      "ident": 13, 
-      "group": "pid_rate", 
-      "name": "yaw_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_ki": {
-      "ident": 12, 
-      "group": "pid_rate", 
-      "name": "yaw_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kd": {
-      "ident": 10, 
-      "group": "pid_rate", 
-      "name": "pitch_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "pid_attitude": {
-    "yaw_kp": {
-      "ident": 20, 
-      "group": "pid_attitude", 
-      "name": "yaw_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kd": {
-      "ident": 16, 
-      "group": "pid_attitude", 
-      "name": "roll_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kp": {
-      "ident": 17, 
-      "group": "pid_attitude", 
-      "name": "pitch_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_ki": {
-      "ident": 15, 
-      "group": "pid_attitude", 
-      "name": "roll_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_ki": {
-      "ident": 18, 
-      "group": "pid_attitude", 
-      "name": "pitch_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kp": {
-      "ident": 14, 
-      "group": "pid_attitude", 
-      "name": "roll_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_kd": {
-      "ident": 22, 
-      "group": "pid_attitude", 
-      "name": "yaw_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_ki": {
-      "ident": 21, 
-      "group": "pid_attitude", 
-      "name": "yaw_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kd": {
-      "ident": 19, 
-      "group": "pid_attitude", 
-      "name": "pitch_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "imu_acc_lpf": {
-    "factor": {
-      "ident": 0, 
-      "group": "imu_acc_lpf", 
-      "name": "factor", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/cflib/cflib/cache/81204C68.json b/src/cflib/cflib/cache/81204C68.json
deleted file mode 100644
index bf0d26da7b36bb2d494b68b27975266918273b8d..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/cache/81204C68.json
+++ /dev/null
@@ -1,317 +0,0 @@
-{
-  "acc": {
-    "y": {
-      "ident": 26, 
-      "group": "acc", 
-      "name": "y", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "x": {
-      "ident": 25, 
-      "group": "acc", 
-      "name": "x", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "z": {
-      "ident": 27, 
-      "group": "acc", 
-      "name": "z", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "zw": {
-      "ident": 28, 
-      "group": "acc", 
-      "name": "zw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "gyro": {
-    "y": {
-      "ident": 4, 
-      "group": "gyro", 
-      "name": "y", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "x": {
-      "ident": 3, 
-      "group": "gyro", 
-      "name": "x", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "z": {
-      "ident": 5, 
-      "group": "gyro", 
-      "name": "z", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "sys": {
-    "canfly": {
-      "ident": 2, 
-      "group": "sys", 
-      "name": "canfly", 
-      "pytype": "<b", 
-      "__class__": "LogTocElement", 
-      "ctype": "int8_t", 
-      "access": 0
-    }
-  }, 
-  "stabilizer": {
-    "thrust": {
-      "ident": 9, 
-      "group": "stabilizer", 
-      "name": "thrust", 
-      "pytype": "<H", 
-      "__class__": "LogTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "yaw": {
-      "ident": 8, 
-      "group": "stabilizer", 
-      "name": "yaw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll": {
-      "ident": 6, 
-      "group": "stabilizer", 
-      "name": "roll", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch": {
-      "ident": 7, 
-      "group": "stabilizer", 
-      "name": "pitch", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "motor": {
-    "m4": {
-      "ident": 21, 
-      "group": "motor", 
-      "name": "m4", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m1": {
-      "ident": 22, 
-      "group": "motor", 
-      "name": "m1", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m3": {
-      "ident": 24, 
-      "group": "motor", 
-      "name": "m3", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m2": {
-      "ident": 23, 
-      "group": "motor", 
-      "name": "m2", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }
-  }, 
-  "altHold": {
-    "vSpeed": {
-      "ident": 18, 
-      "group": "altHold", 
-      "name": "vSpeed", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "target": {
-      "ident": 16, 
-      "group": "altHold", 
-      "name": "target", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "err": {
-      "ident": 15, 
-      "group": "altHold", 
-      "name": "err", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedASL": {
-      "ident": 19, 
-      "group": "altHold", 
-      "name": "vSpeedASL", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedAcc": {
-      "ident": 20, 
-      "group": "altHold", 
-      "name": "vSpeedAcc", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "zSpeed": {
-      "ident": 17, 
-      "group": "altHold", 
-      "name": "zSpeed", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "vpid": {
-    "i": {
-      "ident": 31, 
-      "group": "vpid", 
-      "name": "i", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "p": {
-      "ident": 30, 
-      "group": "vpid", 
-      "name": "p", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pid": {
-      "ident": 29, 
-      "group": "vpid", 
-      "name": "pid", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "d": {
-      "ident": 32, 
-      "group": "vpid", 
-      "name": "d", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "baro": {
-    "aslRaw": {
-      "ident": 11, 
-      "group": "baro", 
-      "name": "aslRaw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "aslLong": {
-      "ident": 12, 
-      "group": "baro", 
-      "name": "aslLong", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pressure": {
-      "ident": 14, 
-      "group": "baro", 
-      "name": "pressure", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "temp": {
-      "ident": 13, 
-      "group": "baro", 
-      "name": "temp", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "asl": {
-      "ident": 10, 
-      "group": "baro", 
-      "name": "asl", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "pm": {
-    "state": {
-      "ident": 1, 
-      "group": "pm", 
-      "name": "state", 
-      "pytype": "<b", 
-      "__class__": "LogTocElement", 
-      "ctype": "int8_t", 
-      "access": 0
-    }, 
-    "vbat": {
-      "ident": 0, 
-      "group": "pm", 
-      "name": "vbat", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/cflib/cflib/cache/892049D2.json b/src/cflib/cflib/cache/892049D2.json
deleted file mode 100644
index 7de8289371fc71c20c9c28d0b3fe5e0ecc9d3945..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/cache/892049D2.json
+++ /dev/null
@@ -1,89 +0,0 @@
-{
-  "stabilizer": {
-    "thrust": {
-      "ident": 4, 
-      "group": "stabilizer", 
-      "name": "thrust", 
-      "pytype": "<H", 
-      "__class__": "LogTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "yaw": {
-      "ident": 3, 
-      "group": "stabilizer", 
-      "name": "yaw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll": {
-      "ident": 1, 
-      "group": "stabilizer", 
-      "name": "roll", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch": {
-      "ident": 2, 
-      "group": "stabilizer", 
-      "name": "pitch", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "motor": {
-    "m4": {
-      "ident": 5, 
-      "group": "motor", 
-      "name": "m4", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m1": {
-      "ident": 6, 
-      "group": "motor", 
-      "name": "m1", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m3": {
-      "ident": 8, 
-      "group": "motor", 
-      "name": "m3", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m2": {
-      "ident": 7, 
-      "group": "motor", 
-      "name": "m2", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }
-  }, 
-  "pm": {
-    "vbat": {
-      "ident": 0, 
-      "group": "pm", 
-      "name": "vbat", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/cflib/cflib/cache/9E5F2E7D.json b/src/cflib/cflib/cache/9E5F2E7D.json
deleted file mode 100644
index 9c5467ac90ae5bfcce962e7c5fd82976199a1634..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/cache/9E5F2E7D.json
+++ /dev/null
@@ -1,355 +0,0 @@
-{
-  "acc": {
-    "y": {
-      "ident": 4, 
-      "group": "acc", 
-      "name": "y", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "x": {
-      "ident": 3, 
-      "group": "acc", 
-      "name": "x", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "z": {
-      "ident": 5, 
-      "group": "acc", 
-      "name": "z", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "zw": {
-      "ident": 6, 
-      "group": "acc", 
-      "name": "zw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "mag2": {
-      "ident": 7, 
-      "group": "acc", 
-      "name": "mag2", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "mag": {
-    "y": {
-      "ident": 35, 
-      "group": "mag", 
-      "name": "y", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "x": {
-      "ident": 34, 
-      "group": "mag", 
-      "name": "x", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "z": {
-      "ident": 36, 
-      "group": "mag", 
-      "name": "z", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "gyro": {
-    "y": {
-      "ident": 28, 
-      "group": "gyro", 
-      "name": "y", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "x": {
-      "ident": 27, 
-      "group": "gyro", 
-      "name": "x", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "z": {
-      "ident": 29, 
-      "group": "gyro", 
-      "name": "z", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "sys": {
-    "canfly": {
-      "ident": 2, 
-      "group": "sys", 
-      "name": "canfly", 
-      "pytype": "<b", 
-      "__class__": "LogTocElement", 
-      "ctype": "int8_t", 
-      "access": 0
-    }
-  }, 
-  "stabilizer": {
-    "thrust": {
-      "ident": 20, 
-      "group": "stabilizer", 
-      "name": "thrust", 
-      "pytype": "<H", 
-      "__class__": "LogTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "yaw": {
-      "ident": 19, 
-      "group": "stabilizer", 
-      "name": "yaw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll": {
-      "ident": 17, 
-      "group": "stabilizer", 
-      "name": "roll", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch": {
-      "ident": 18, 
-      "group": "stabilizer", 
-      "name": "pitch", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "motor": {
-    "m4": {
-      "ident": 13, 
-      "group": "motor", 
-      "name": "m4", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m1": {
-      "ident": 14, 
-      "group": "motor", 
-      "name": "m1", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m3": {
-      "ident": 16, 
-      "group": "motor", 
-      "name": "m3", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }, 
-    "m2": {
-      "ident": 15, 
-      "group": "motor", 
-      "name": "m2", 
-      "pytype": "<i", 
-      "__class__": "LogTocElement", 
-      "ctype": "int32_t", 
-      "access": 0
-    }
-  }, 
-  "altHold": {
-    "vSpeed": {
-      "ident": 24, 
-      "group": "altHold", 
-      "name": "vSpeed", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "target": {
-      "ident": 22, 
-      "group": "altHold", 
-      "name": "target", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "err": {
-      "ident": 21, 
-      "group": "altHold", 
-      "name": "err", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedASL": {
-      "ident": 25, 
-      "group": "altHold", 
-      "name": "vSpeedASL", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedAcc": {
-      "ident": 26, 
-      "group": "altHold", 
-      "name": "vSpeedAcc", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "zSpeed": {
-      "ident": 23, 
-      "group": "altHold", 
-      "name": "zSpeed", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "vpid": {
-    "i": {
-      "ident": 32, 
-      "group": "vpid", 
-      "name": "i", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "p": {
-      "ident": 31, 
-      "group": "vpid", 
-      "name": "p", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pid": {
-      "ident": 30, 
-      "group": "vpid", 
-      "name": "pid", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "d": {
-      "ident": 33, 
-      "group": "vpid", 
-      "name": "d", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "baro": {
-    "aslRaw": {
-      "ident": 9, 
-      "group": "baro", 
-      "name": "aslRaw", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "aslLong": {
-      "ident": 10, 
-      "group": "baro", 
-      "name": "aslLong", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pressure": {
-      "ident": 12, 
-      "group": "baro", 
-      "name": "pressure", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "temp": {
-      "ident": 11, 
-      "group": "baro", 
-      "name": "temp", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "asl": {
-      "ident": 8, 
-      "group": "baro", 
-      "name": "asl", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "pm": {
-    "state": {
-      "ident": 1, 
-      "group": "pm", 
-      "name": "state", 
-      "pytype": "<b", 
-      "__class__": "LogTocElement", 
-      "ctype": "int8_t", 
-      "access": 0
-    }, 
-    "vbat": {
-      "ident": 0, 
-      "group": "pm", 
-      "name": "vbat", 
-      "pytype": "<f", 
-      "__class__": "LogTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/cflib/cflib/cache/E20076B8.json b/src/cflib/cflib/cache/E20076B8.json
deleted file mode 100644
index ca46a4a32a276732106252199be7b54d2283d214..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/cache/E20076B8.json
+++ /dev/null
@@ -1,499 +0,0 @@
-{
-  "imu_sensors": {
-    "HMC5883L": {
-      "ident": 3, 
-      "group": "imu_sensors", 
-      "name": "HMC5883L", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }, 
-    "MS5611": {
-      "ident": 4, 
-      "group": "imu_sensors", 
-      "name": "MS5611", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }
-  }, 
-  "sensorfusion6": {
-    "ki": {
-      "ident": 30, 
-      "group": "sensorfusion6", 
-      "name": "ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kp": {
-      "ident": 29, 
-      "group": "sensorfusion6", 
-      "name": "kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "flightmode": {
-    "althold": {
-      "ident": 10, 
-      "group": "flightmode", 
-      "name": "althold", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 0
-    }
-  }, 
-  "firmware": {
-    "revision0": {
-      "ident": 50, 
-      "group": "firmware", 
-      "name": "revision0", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }, 
-    "revision1": {
-      "ident": 51, 
-      "group": "firmware", 
-      "name": "revision1", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 1
-    }, 
-    "modified": {
-      "ident": 52, 
-      "group": "firmware", 
-      "name": "modified", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }
-  }, 
-  "cpu": {
-    "flash": {
-      "ident": 6, 
-      "group": "cpu", 
-      "name": "flash", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 1
-    }, 
-    "id2": {
-      "ident": 9, 
-      "group": "cpu", 
-      "name": "id2", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }, 
-    "id0": {
-      "ident": 7, 
-      "group": "cpu", 
-      "name": "id0", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }, 
-    "id1": {
-      "ident": 8, 
-      "group": "cpu", 
-      "name": "id1", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }
-  }, 
-  "pid_rate": {
-    "yaw_kp": {
-      "ident": 17, 
-      "group": "pid_rate", 
-      "name": "yaw_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kd": {
-      "ident": 13, 
-      "group": "pid_rate", 
-      "name": "roll_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kp": {
-      "ident": 14, 
-      "group": "pid_rate", 
-      "name": "pitch_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_ki": {
-      "ident": 12, 
-      "group": "pid_rate", 
-      "name": "roll_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_ki": {
-      "ident": 15, 
-      "group": "pid_rate", 
-      "name": "pitch_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kp": {
-      "ident": 11, 
-      "group": "pid_rate", 
-      "name": "roll_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_kd": {
-      "ident": 19, 
-      "group": "pid_rate", 
-      "name": "yaw_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_ki": {
-      "ident": 18, 
-      "group": "pid_rate", 
-      "name": "yaw_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kd": {
-      "ident": 16, 
-      "group": "pid_rate", 
-      "name": "pitch_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "pid_attitude": {
-    "yaw_kp": {
-      "ident": 26, 
-      "group": "pid_attitude", 
-      "name": "yaw_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kd": {
-      "ident": 22, 
-      "group": "pid_attitude", 
-      "name": "roll_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kp": {
-      "ident": 23, 
-      "group": "pid_attitude", 
-      "name": "pitch_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_ki": {
-      "ident": 21, 
-      "group": "pid_attitude", 
-      "name": "roll_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_ki": {
-      "ident": 24, 
-      "group": "pid_attitude", 
-      "name": "pitch_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kp": {
-      "ident": 20, 
-      "group": "pid_attitude", 
-      "name": "roll_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_kd": {
-      "ident": 28, 
-      "group": "pid_attitude", 
-      "name": "yaw_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_ki": {
-      "ident": 27, 
-      "group": "pid_attitude", 
-      "name": "yaw_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kd": {
-      "ident": 25, 
-      "group": "pid_attitude", 
-      "name": "pitch_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "altHold": {
-    "vSpeedAccFac": {
-      "ident": 43, 
-      "group": "altHold", 
-      "name": "vSpeedAccFac", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedASLDeadband": {
-      "ident": 44, 
-      "group": "altHold", 
-      "name": "vSpeedASLDeadband", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "errDeadband": {
-      "ident": 33, 
-      "group": "altHold", 
-      "name": "errDeadband", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "altHoldErrMax": {
-      "ident": 35, 
-      "group": "altHold", 
-      "name": "altHoldErrMax", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kd": {
-      "ident": 36, 
-      "group": "altHold", 
-      "name": "kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pidAslFac": {
-      "ident": 40, 
-      "group": "altHold", 
-      "name": "pidAslFac", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "maxThrust": {
-      "ident": 48, 
-      "group": "altHold", 
-      "name": "maxThrust", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "ki": {
-      "ident": 37, 
-      "group": "altHold", 
-      "name": "ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedLimit": {
-      "ident": 46, 
-      "group": "altHold", 
-      "name": "vSpeedLimit", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "aslAlpha": {
-      "ident": 31, 
-      "group": "altHold", 
-      "name": "aslAlpha", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kp": {
-      "ident": 38, 
-      "group": "altHold", 
-      "name": "kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "baseThrust": {
-      "ident": 47, 
-      "group": "altHold", 
-      "name": "baseThrust", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "vBiasAlpha": {
-      "ident": 42, 
-      "group": "altHold", 
-      "name": "vBiasAlpha", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pidAlpha": {
-      "ident": 39, 
-      "group": "altHold", 
-      "name": "pidAlpha", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "altHoldChangeSens": {
-      "ident": 34, 
-      "group": "altHold", 
-      "name": "altHoldChangeSens", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "minThrust": {
-      "ident": 49, 
-      "group": "altHold", 
-      "name": "minThrust", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "vAccDeadband": {
-      "ident": 41, 
-      "group": "altHold", 
-      "name": "vAccDeadband", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "aslAlphaLong": {
-      "ident": 32, 
-      "group": "altHold", 
-      "name": "aslAlphaLong", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedASLFac": {
-      "ident": 45, 
-      "group": "altHold", 
-      "name": "vSpeedASLFac", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "imu_tests": {
-    "HMC5883L": {
-      "ident": 1, 
-      "group": "imu_tests", 
-      "name": "HMC5883L", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }, 
-    "MS5611": {
-      "ident": 2, 
-      "group": "imu_tests", 
-      "name": "MS5611", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }, 
-    "MPU6050": {
-      "ident": 0, 
-      "group": "imu_tests", 
-      "name": "MPU6050", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }
-  }, 
-  "imu_acc_lpf": {
-    "factor": {
-      "ident": 5, 
-      "group": "imu_acc_lpf", 
-      "name": "factor", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/cflib/cflib/cache/E8BC7DAD.json b/src/cflib/cflib/cache/E8BC7DAD.json
deleted file mode 100644
index ca46a4a32a276732106252199be7b54d2283d214..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/cache/E8BC7DAD.json
+++ /dev/null
@@ -1,499 +0,0 @@
-{
-  "imu_sensors": {
-    "HMC5883L": {
-      "ident": 3, 
-      "group": "imu_sensors", 
-      "name": "HMC5883L", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }, 
-    "MS5611": {
-      "ident": 4, 
-      "group": "imu_sensors", 
-      "name": "MS5611", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }
-  }, 
-  "sensorfusion6": {
-    "ki": {
-      "ident": 30, 
-      "group": "sensorfusion6", 
-      "name": "ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kp": {
-      "ident": 29, 
-      "group": "sensorfusion6", 
-      "name": "kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "flightmode": {
-    "althold": {
-      "ident": 10, 
-      "group": "flightmode", 
-      "name": "althold", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 0
-    }
-  }, 
-  "firmware": {
-    "revision0": {
-      "ident": 50, 
-      "group": "firmware", 
-      "name": "revision0", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }, 
-    "revision1": {
-      "ident": 51, 
-      "group": "firmware", 
-      "name": "revision1", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 1
-    }, 
-    "modified": {
-      "ident": 52, 
-      "group": "firmware", 
-      "name": "modified", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }
-  }, 
-  "cpu": {
-    "flash": {
-      "ident": 6, 
-      "group": "cpu", 
-      "name": "flash", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 1
-    }, 
-    "id2": {
-      "ident": 9, 
-      "group": "cpu", 
-      "name": "id2", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }, 
-    "id0": {
-      "ident": 7, 
-      "group": "cpu", 
-      "name": "id0", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }, 
-    "id1": {
-      "ident": 8, 
-      "group": "cpu", 
-      "name": "id1", 
-      "pytype": "<L", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint32_t", 
-      "access": 1
-    }
-  }, 
-  "pid_rate": {
-    "yaw_kp": {
-      "ident": 17, 
-      "group": "pid_rate", 
-      "name": "yaw_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kd": {
-      "ident": 13, 
-      "group": "pid_rate", 
-      "name": "roll_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kp": {
-      "ident": 14, 
-      "group": "pid_rate", 
-      "name": "pitch_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_ki": {
-      "ident": 12, 
-      "group": "pid_rate", 
-      "name": "roll_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_ki": {
-      "ident": 15, 
-      "group": "pid_rate", 
-      "name": "pitch_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kp": {
-      "ident": 11, 
-      "group": "pid_rate", 
-      "name": "roll_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_kd": {
-      "ident": 19, 
-      "group": "pid_rate", 
-      "name": "yaw_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_ki": {
-      "ident": 18, 
-      "group": "pid_rate", 
-      "name": "yaw_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kd": {
-      "ident": 16, 
-      "group": "pid_rate", 
-      "name": "pitch_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "pid_attitude": {
-    "yaw_kp": {
-      "ident": 26, 
-      "group": "pid_attitude", 
-      "name": "yaw_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kd": {
-      "ident": 22, 
-      "group": "pid_attitude", 
-      "name": "roll_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kp": {
-      "ident": 23, 
-      "group": "pid_attitude", 
-      "name": "pitch_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_ki": {
-      "ident": 21, 
-      "group": "pid_attitude", 
-      "name": "roll_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_ki": {
-      "ident": 24, 
-      "group": "pid_attitude", 
-      "name": "pitch_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "roll_kp": {
-      "ident": 20, 
-      "group": "pid_attitude", 
-      "name": "roll_kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_kd": {
-      "ident": 28, 
-      "group": "pid_attitude", 
-      "name": "yaw_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "yaw_ki": {
-      "ident": 27, 
-      "group": "pid_attitude", 
-      "name": "yaw_ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pitch_kd": {
-      "ident": 25, 
-      "group": "pid_attitude", 
-      "name": "pitch_kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "altHold": {
-    "vSpeedAccFac": {
-      "ident": 43, 
-      "group": "altHold", 
-      "name": "vSpeedAccFac", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedASLDeadband": {
-      "ident": 44, 
-      "group": "altHold", 
-      "name": "vSpeedASLDeadband", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "errDeadband": {
-      "ident": 33, 
-      "group": "altHold", 
-      "name": "errDeadband", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "altHoldErrMax": {
-      "ident": 35, 
-      "group": "altHold", 
-      "name": "altHoldErrMax", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kd": {
-      "ident": 36, 
-      "group": "altHold", 
-      "name": "kd", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pidAslFac": {
-      "ident": 40, 
-      "group": "altHold", 
-      "name": "pidAslFac", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "maxThrust": {
-      "ident": 48, 
-      "group": "altHold", 
-      "name": "maxThrust", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "ki": {
-      "ident": 37, 
-      "group": "altHold", 
-      "name": "ki", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedLimit": {
-      "ident": 46, 
-      "group": "altHold", 
-      "name": "vSpeedLimit", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "aslAlpha": {
-      "ident": 31, 
-      "group": "altHold", 
-      "name": "aslAlpha", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "kp": {
-      "ident": 38, 
-      "group": "altHold", 
-      "name": "kp", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "baseThrust": {
-      "ident": 47, 
-      "group": "altHold", 
-      "name": "baseThrust", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "vBiasAlpha": {
-      "ident": 42, 
-      "group": "altHold", 
-      "name": "vBiasAlpha", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "pidAlpha": {
-      "ident": 39, 
-      "group": "altHold", 
-      "name": "pidAlpha", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "altHoldChangeSens": {
-      "ident": 34, 
-      "group": "altHold", 
-      "name": "altHoldChangeSens", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "minThrust": {
-      "ident": 49, 
-      "group": "altHold", 
-      "name": "minThrust", 
-      "pytype": "<H", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint16_t", 
-      "access": 0
-    }, 
-    "vAccDeadband": {
-      "ident": 41, 
-      "group": "altHold", 
-      "name": "vAccDeadband", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "aslAlphaLong": {
-      "ident": 32, 
-      "group": "altHold", 
-      "name": "aslAlphaLong", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }, 
-    "vSpeedASLFac": {
-      "ident": 45, 
-      "group": "altHold", 
-      "name": "vSpeedASLFac", 
-      "pytype": "<f", 
-      "__class__": "ParamTocElement", 
-      "ctype": "float", 
-      "access": 0
-    }
-  }, 
-  "imu_tests": {
-    "HMC5883L": {
-      "ident": 1, 
-      "group": "imu_tests", 
-      "name": "HMC5883L", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }, 
-    "MS5611": {
-      "ident": 2, 
-      "group": "imu_tests", 
-      "name": "MS5611", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }, 
-    "MPU6050": {
-      "ident": 0, 
-      "group": "imu_tests", 
-      "name": "MPU6050", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 1
-    }
-  }, 
-  "imu_acc_lpf": {
-    "factor": {
-      "ident": 5, 
-      "group": "imu_acc_lpf", 
-      "name": "factor", 
-      "pytype": "<B", 
-      "__class__": "ParamTocElement", 
-      "ctype": "uint8_t", 
-      "access": 0
-    }
-  }
-}
\ No newline at end of file
diff --git a/src/cflib/cflib/crazyflie/__init__.py b/src/cflib/cflib/crazyflie/__init__.py
deleted file mode 100644
index 698fef1eca0b632a9b1f62c83401ab91f4bc1ef6..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/__init__.py
+++ /dev/null
@@ -1,400 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-The Crazyflie module is used to easily connect/send/receive data
-from a Crazyflie.
-
-Each function in the Crazyflie has a class in the module that can be used
-to access that functionality. The same design is then used in the Crazyflie
-firmware which makes the mapping 1:1 in most cases.
-"""
-
-import logging
-
-import time
-import datetime
-from threading import Thread
-from threading import Timer, Lock
-from collections import namedtuple
-
-from .commander import Commander
-from .console import Console
-from .param import Param
-from .log import Log
-from .toccache import TocCache
-from .mem import Memory
-from .platformservice import PlatformService
-
-import cflib.crtp
-
-from cflib.utils.callbacks import Caller
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Crazyflie']
-
-logger = logging.getLogger(__name__)
-
-
-class State:
-    """Stat of the connection procedure"""
-    DISCONNECTED = 0
-    INITIALIZED = 1
-    CONNECTED = 2
-    SETUP_FINISHED = 3
-
-
-class Crazyflie():
-    """The Crazyflie class"""
-
-    # Called on disconnect, no matter the reason
-    disconnected = Caller()
-    # Called on unintentional disconnect only
-    connection_lost = Caller()
-    # Called when the first packet in a new link is received
-    link_established = Caller()
-    # Called when the user requests a connection
-    connection_requested = Caller()
-    # Called when the link is established and the TOCs (that are not cached)
-    # have been downloaded
-    connected = Caller()
-    # Called if establishing of the link fails (i.e times out)
-    connection_failed = Caller()
-    # Called for every packet received
-    packet_received = Caller()
-    # Called for every packet sent
-    packet_sent = Caller()
-    # Called when the link driver updates the link quality measurement
-    link_quality_updated = Caller()
-
-    state = State.DISCONNECTED
-
-    def __init__(self, link=None, ro_cache=None, rw_cache=None):
-        """
-        Create the objects from this module and register callbacks.
-
-        ro_cache -- Path to read-only cache (string)
-        rw_cache -- Path to read-write cache (string)
-        """
-        self.link = link
-        self._toc_cache = TocCache(ro_cache=ro_cache,
-                                   rw_cache=rw_cache)
-
-        self.incoming = _IncomingPacketHandler(self)
-        self.incoming.setDaemon(True)
-        self.incoming.start()
-
-        self.commander = Commander(self)
-        self.log = Log(self)
-        self.console = Console(self)
-        self.param = Param(self)
-        self.mem = Memory(self)
-        self.platform = PlatformService(self)
-
-        self.link_uri = ""
-
-        # Used for retry when no reply was sent back
-        self.packet_received.add_callback(self._check_for_initial_packet_cb)
-        self.packet_received.add_callback(self._check_for_answers)
-
-        self._answer_patterns = {}
-
-        self._send_lock = Lock()
-
-        self.connected_ts = None
-
-        # Connect callbacks to logger
-        self.disconnected.add_callback(
-            lambda uri: logger.info("Callback->Disconnected from [%s]", uri))
-        self.disconnected.add_callback(self._disconnected)
-        self.link_established.add_callback(
-            lambda uri: logger.info("Callback->Connected to [%s]", uri))
-        self.connection_lost.add_callback(
-            lambda uri, errmsg: logger.info(
-                "Callback->Connection lost to [%s]: %s", uri, errmsg))
-        self.connection_failed.add_callback(
-            lambda uri, errmsg: logger.info(
-                "Callback->Connected failed to [%s]: %s", uri, errmsg))
-        self.connection_requested.add_callback(
-            lambda uri: logger.info(
-                "Callback->Connection initialized[%s]", uri))
-        self.connected.add_callback(
-            lambda uri: logger.info(
-                "Callback->Connection setup finished [%s]", uri))
-
-    def _disconnected(self, link_uri):
-        """ Callback when disconnected."""
-        self.connected_ts = None
-
-    def _start_connection_setup(self):
-        """Start the connection setup by refreshing the TOCs"""
-        logger.info("We are connected[%s], request connection setup",
-                    self.link_uri)
-        self.log.refresh_toc(self._log_toc_updated_cb, self._toc_cache)
-
-    def _param_toc_updated_cb(self):
-        """Called when the param TOC has been fully updated"""
-        logger.info("Param TOC finished updating")
-        self.connected_ts = datetime.datetime.now()
-        self.connected.call(self.link_uri)
-        # Trigger the update for all the parameters
-        self.param.request_update_of_all_params()
-
-    def _mems_updated_cb(self):
-        """Called when the memories have been identified"""
-        logger.info("Memories finished updating")
-        self.param.refresh_toc(self._param_toc_updated_cb, self._toc_cache)
-
-    def _log_toc_updated_cb(self):
-        """Called when the log TOC has been fully updated"""
-        logger.info("Log TOC finished updating")
-        self.mem.refresh(self._mems_updated_cb)
-
-    def _link_error_cb(self, errmsg):
-        """Called from the link driver when there's an error"""
-        logger.warning("Got link error callback [%s] in state [%s]",
-                       errmsg, self.state)
-        if (self.link is not None):
-            self.link.close()
-        self.link = None
-        if (self.state == State.INITIALIZED):
-            self.connection_failed.call(self.link_uri, errmsg)
-        if (self.state == State.CONNECTED or
-                self.state == State.SETUP_FINISHED):
-            self.disconnected.call(self.link_uri)
-            self.connection_lost.call(self.link_uri, errmsg)
-        self.state = State.DISCONNECTED
-
-    def _link_quality_cb(self, percentage):
-        """Called from link driver to report link quality"""
-        self.link_quality_updated.call(percentage)
-
-    def _check_for_initial_packet_cb(self, data):
-        """
-        Called when first packet arrives from Crazyflie.
-
-        This is used to determine if we are connected to something that is
-        answering.
-        """
-        self.state = State.CONNECTED
-        self.link_established.call(self.link_uri)
-        self.packet_received.remove_callback(self._check_for_initial_packet_cb)
-
-    def open_link(self, link_uri):
-        """
-        Open the communication link to a copter at the given URI and setup the
-        connection (download log/parameter TOC).
-        """
-        self.connection_requested.call(link_uri)
-        self.state = State.INITIALIZED
-        self.link_uri = link_uri
-        try:
-            self.link = cflib.crtp.get_link_driver(
-                link_uri, self._link_quality_cb, self._link_error_cb)
-
-            if not self.link:
-                message = "No driver found or malformed URI: {}" \
-                    .format(link_uri)
-                logger.warning(message)
-                self.connection_failed.call(link_uri, message)
-            else:
-                # Add a callback so we can check that any data is coming
-                # back from the copter
-                self.packet_received.add_callback(
-                    self._check_for_initial_packet_cb)
-
-                self._start_connection_setup()
-        except Exception as ex:  # pylint: disable=W0703
-            # We want to catch every possible exception here and show
-            # it in the user interface
-            import traceback
-
-            logger.error("Couldn't load link driver: %s\n\n%s",
-                         ex, traceback.format_exc())
-            exception_text = "Couldn't load link driver: %s\n\n%s" % (
-                ex, traceback.format_exc())
-            if self.link:
-                self.link.close()
-                self.link = None
-            self.connection_failed.call(link_uri, exception_text)
-
-    def close_link(self):
-        """Close the communication link."""
-        logger.info("Closing link")
-        if (self.link is not None):
-            self.commander.send_setpoint(0, 0, 0, 0)
-        if (self.link is not None):
-            self.link.close()
-            self.link = None
-        self._answer_patterns = {}
-        self.disconnected.call(self.link_uri)
-
-    def add_port_callback(self, port, cb):
-        """Add a callback to cb on port"""
-        self.incoming.add_port_callback(port, cb)
-
-    def remove_port_callback(self, port, cb):
-        """Remove the callback cb on port"""
-        self.incoming.remove_port_callback(port, cb)
-
-    def _no_answer_do_retry(self, pk, pattern):
-        """Resend packets that we have not gotten answers to"""
-        logger.info("Resending for pattern %s", pattern)
-        # Set the timer to None before trying to send again
-        self.send_packet(pk, expected_reply=pattern, resend=True)
-
-    def _check_for_answers(self, pk):
-        """
-        Callback called for every packet received to check if we are
-        waiting for an answer on this port. If so, then cancel the retry
-        timer.
-        """
-        longest_match = ()
-        if len(self._answer_patterns) > 0:
-            data = (pk.header,) + tuple(pk.data)
-            for p in list(self._answer_patterns.keys()):
-                logger.debug("Looking for pattern match on %s vs %s", p, data)
-                if len(p) <= len(data):
-                    if p == data[0:len(p)]:
-                        match = data[0:len(p)]
-                        if len(match) >= len(longest_match):
-                            logger.debug("Found new longest match %s", match)
-                            longest_match = match
-        if len(longest_match) > 0:
-            self._answer_patterns[longest_match].cancel()
-            del self._answer_patterns[longest_match]
-
-    def send_packet(self, pk, expected_reply=(), resend=False, timeout=0.2):
-        """
-        Send a packet through the link interface.
-
-        pk -- Packet to send
-        expect_answer -- True if a packet from the Crazyflie is expected to
-                         be sent back, otherwise false
-
-        """
-        self._send_lock.acquire()
-        if self.link is not None:
-            if len(expected_reply) > 0 and not resend and \
-                    self.link.needs_resending:
-                pattern = (pk.header,) + expected_reply
-                logger.debug(
-                    "Sending packet and expecting the %s pattern back",
-                    pattern)
-                new_timer = Timer(timeout,
-                                  lambda: self._no_answer_do_retry(pk,
-                                                                   pattern))
-                self._answer_patterns[pattern] = new_timer
-                new_timer.start()
-            elif resend:
-                # Check if we have gotten an answer, if not try again
-                pattern = expected_reply
-                if pattern in self._answer_patterns:
-                    logger.debug("We want to resend and the pattern is there")
-                    if self._answer_patterns[pattern]:
-                        new_timer = Timer(timeout,
-                                          lambda:
-                                          self._no_answer_do_retry(
-                                              pk, pattern))
-                        self._answer_patterns[pattern] = new_timer
-                        new_timer.start()
-                else:
-                    logger.debug("Resend requested, but no pattern found: %s",
-                                 self._answer_patterns)
-            self.link.send_packet(pk)
-            self.packet_sent.call(pk)
-        self._send_lock.release()
-
-
-_CallbackContainer = namedtuple("CallbackConstainer",
-                                "port port_mask channel channel_mask callback")
-
-
-class _IncomingPacketHandler(Thread):
-    """Handles incoming packets and sends the data to the correct receivers"""
-
-    def __init__(self, cf):
-        Thread.__init__(self)
-        self.cf = cf
-        self.cb = []
-
-    def add_port_callback(self, port, cb):
-        """Add a callback for data that comes on a specific port"""
-        logger.debug("Adding callback on port [%d] to [%s]", port, cb)
-        self.add_header_callback(cb, port, 0, 0xff, 0x0)
-
-    def remove_port_callback(self, port, cb):
-        """Remove a callback for data that comes on a specific port"""
-        logger.debug("Removing callback on port [%d] to [%s]", port, cb)
-        for port_callback in self.cb:
-            if port_callback.port == port and port_callback.callback == cb:
-                self.cb.remove(port_callback)
-
-    def add_header_callback(self, cb, port, channel, port_mask=0xFF,
-                            channel_mask=0xFF):
-        """
-        Add a callback for a specific port/header callback with the
-        possibility to add a mask for channel and port for multiple
-        hits for same callback.
-        """
-        self.cb.append(_CallbackContainer(port, port_mask,
-                                          channel, channel_mask, cb))
-
-    def run(self):
-        while True:
-            if self.cf.link is None:
-                time.sleep(1)
-                continue
-            pk = self.cf.link.receive_packet(1)
-
-            if pk is None:
-                continue
-
-            # All-packet callbacks
-            self.cf.packet_received.call(pk)
-
-            found = False
-            for cb in (cb for cb in self.cb
-                       if cb.port == (pk.port & cb.port_mask) and
-                       cb.channel == (pk.channel & cb.channel_mask)):
-                try:
-                    cb.callback(pk)
-                except Exception:  # pylint: disable=W0703
-                    # Disregard pylint warning since we want to catch all
-                    # exceptions and we can't know what will happen in
-                    # the callbacks.
-                    import traceback
-
-                    logger.warning("Exception while doing callback on port"
-                                   " [%d]\n\n%s", pk.port,
-                                   traceback.format_exc())
-                if cb.port != 0xFF:
-                    found = True
-
-            if not found:
-                pass
diff --git a/src/cflib/cflib/crazyflie/commander.py b/src/cflib/cflib/crazyflie/commander.py
deleted file mode 100644
index e791887c1e23d702dd03d0d1cd21dddd2ce83333..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/commander.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Used for sending control setpoints to the Crazyflie
-"""
-
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
-import struct
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Commander']
-
-
-class Commander():
-    """
-    Used for sending control setpoints to the Crazyflie
-    """
-
-    def __init__(self, crazyflie=None):
-        """
-        Initialize the commander object. By default the commander is in
-        +-mode (not x-mode).
-        """
-        self._cf = crazyflie
-        self._x_mode = False
-
-    def set_client_xmode(self, enabled):
-        """
-        Enable/disable the client side X-mode. When enabled this recalculates
-        the setpoints before sending them to the Crazyflie.
-        """
-        self._x_mode = enabled
-
-    def send_setpoint(self, roll, pitch, yaw, thrust):
-        """
-        Send a new control setpoint for roll/pitch/yaw/thrust to the copter
-
-        The arguments roll/pitch/yaw/trust is the new setpoints that should
-        be sent to the copter
-        """
-        if thrust > 0xFFFF or thrust < 0:
-            raise ValueError("Thrust must be between 0 and 0xFFFF")
-
-        if self._x_mode:
-            roll, pitch = 0.707 * (roll - pitch), 0.707 * (roll + pitch)
-
-        pk = CRTPPacket()
-        pk.port = CRTPPort.COMMANDER
-        pk.data = struct.pack('<fffH', roll, -pitch, yaw, thrust)
-        self._cf.send_packet(pk)
diff --git a/src/cflib/cflib/crazyflie/console.py b/src/cflib/cflib/crazyflie/console.py
deleted file mode 100644
index 26b9f9fda5e478178b95dffa4308bcbc2a85d669..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/console.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-"""
-Crazyflie console is used to receive characters printed using printf
-from the firmware.
-"""
-
-import struct
-from cflib.utils.callbacks import Caller
-from cflib.crtp.crtpstack import CRTPPort
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Console']
-
-
-class Console:
-    """
-    Crazyflie console is used to receive characters printed using printf
-    from the firmware.
-    """
-
-    receivedChar = Caller()
-
-    def __init__(self, crazyflie):
-        """
-        Initialize the console and register it to receive data from the copter.
-        """
-        self.cf = crazyflie
-        self.cf.add_port_callback(CRTPPort.CONSOLE, self.incoming)
-
-    def incoming(self, packet):
-        """
-        Callback for data received from the copter.
-        """
-        # This might be done prettier ;-)
-        console_text = packet.data.decode("UTF-8")
-
-        self.receivedChar.call(console_text)
diff --git a/src/cflib/cflib/crazyflie/log.py b/src/cflib/cflib/crazyflie/log.py
deleted file mode 100644
index ca52eed48496da8712c4acc9292cc7541fc089a8..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/log.py
+++ /dev/null
@@ -1,557 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Enables logging of variables from the Crazyflie.
-
-When a Crazyflie is connected it's possible to download a TableOfContent of all
-the variables that can be logged. Using this it's possible to add logging
-configurations where selected variables are sent to the client at a
-specified period.
-
-Terminology:
-  Log configuration - A configuration with a period and a number of variables
-                      that are present in the TOC.
-  Stored as         - The size and type of the variable as declared in the
-                      Crazyflie firmware
-  Fetch as          - The size and type that a variable should be fetched as.
-                      This does not have to be the same as the size and type
-                      it's stored as.
-
-States of a configuration:
-  Created on host - When a configuration is created the contents is checked
-                    so that all the variables are present in the TOC. If not
-                    then the configuration cannot be created.
-  Created on CF   - When the configuration is deemed valid it is added to the
-                    Crazyflie. At this time the memory constraint is checked
-                    and the status returned.
-  Started on CF   - Any added block that is not started can be started. Once
-                    started the Crazyflie will send back logdata periodically
-                    according to the specified period when it's created.
-  Stopped on CF   - Any started configuration can be stopped. The memory taken
-                    by the configuration on the Crazyflie is NOT freed, the
-                    only effect is that the Crazyflie will stop sending
-                    logdata back to the host.
-  Deleted on CF   - Any block that is added can be deleted. When this is done
-                    the memory taken by the configuration is freed on the
-                    Crazyflie. The configuration will have to be re-added to
-                    be used again.
-"""
-
-import struct
-import errno
-import sys
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
-from cflib.utils.callbacks import Caller
-from .toc import Toc, TocFetcher
-import logging
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Log', 'LogTocElement']
-
-# Channels used for the logging port
-CHAN_TOC = 0
-CHAN_SETTINGS = 1
-CHAN_LOGDATA = 2
-
-# Commands used when accessing the Table of Contents
-CMD_TOC_ELEMENT = 0
-CMD_TOC_INFO = 1
-
-# Commands used when accessing the Log configurations
-CMD_CREATE_BLOCK = 0
-CMD_APPEND_BLOCK = 1
-CMD_DELETE_BLOCK = 2
-CMD_START_LOGGING = 3
-CMD_STOP_LOGGING = 4
-CMD_RESET_LOGGING = 5
-
-# Possible states when receiving TOC
-IDLE = "IDLE"
-GET_TOC_INF = "GET_TOC_INFO"
-GET_TOC_ELEMENT = "GET_TOC_ELEMENT"
-
-# The max size of a CRTP packet payload
-MAX_LOG_DATA_PACKET_SIZE = 30
-
-
-logger = logging.getLogger(__name__)
-
-
-class LogVariable():
-    """A logging variable"""
-
-    TOC_TYPE = 0
-    MEM_TYPE = 1
-
-    def __init__(self, name="", fetchAs="uint8_t", varType=TOC_TYPE,
-                 storedAs="", address=0):
-        self.name = name
-        self.fetch_as = LogTocElement.get_id_from_cstring(fetchAs)
-        if (len(storedAs) == 0):
-            self.stored_as = self.fetch_as
-        else:
-            self.stored_as = LogTocElement.get_id_from_cstring(storedAs)
-        self.address = address
-        self.type = varType
-        self.stored_as_string = storedAs
-        self.fetch_as_string = fetchAs
-
-    def is_toc_variable(self):
-        """
-        Return true if the variable should be in the TOC, false if raw memory
-        variable
-        """
-        return self.type == LogVariable.TOC_TYPE
-
-    def get_storage_and_fetch_byte(self):
-        """Return what the variable is stored as and fetched as"""
-        return (self.fetch_as | (self.stored_as << 4))
-
-    def __str__(self):
-        return ("LogVariable: name=%s, store=%s, fetch=%s" %
-                (self.name, LogTocElement.get_cstring_from_id(self.stored_as),
-                 LogTocElement.get_cstring_from_id(self.fetch_as)))
-
-
-class LogConfig(object):
-    """Representation of one log configuration that enables logging
-    from the Crazyflie"""
-    _config_id_counter = 1
-
-    def __init__(self, name, period_in_ms):
-        """Initialize the entry"""
-        self.data_received_cb = Caller()
-        self.error_cb = Caller()
-        self.started_cb = Caller()
-        self.added_cb = Caller()
-        self.err_no = 0
-
-        self.id = LogConfig._config_id_counter
-        LogConfig._config_id_counter = (LogConfig._config_id_counter + 1) % 255
-        self.cf = None
-        self.period = int(period_in_ms / 10)
-        self.period_in_ms = period_in_ms
-        self._added = False
-        self._started = False
-        self.valid = False
-        self.variables = []
-        self.default_fetch_as = []
-        self.name = name
-
-    def add_variable(self, name, fetch_as=None):
-        """Add a new variable to the configuration.
-
-        name - Complete name of the variable in the form group.name
-        fetch_as - String representation of the type the variable should be
-                   fetched as (i.e uint8_t, float, FP16, etc)
-
-        If no fetch_as type is supplied, then the stored as type will be used
-        (i.e the type of the fetched variable is the same as it's stored in the
-        Crazyflie)."""
-        if fetch_as:
-            self.variables.append(LogVariable(name, fetch_as))
-        else:
-            # We cannot determine the default type until we have connected. So
-            # save the name and we will add these once we are connected.
-            self.default_fetch_as.append(name)
-
-    def add_memory(self, name, fetch_as, stored_as, address):
-        """Add a raw memory position to log.
-
-        name - Arbitrary name of the variable
-        fetch_as - String representation of the type of the data the memory
-                   should be fetch as (i.e uint8_t, float, FP16)
-        stored_as - String representation of the type the data is stored as
-                    in the Crazyflie
-        address - The address of the data
-        """
-        self.variables.append(LogVariable(name, fetch_as, LogVariable.MEM_TYPE,
-                                          stored_as, address))
-
-    def _set_added(self, added):
-        if added != self._added:
-            self.added_cb.call(self, added)
-        self._added = added
-
-    def _get_added(self):
-        return self._added
-
-    def _set_started(self, started):
-        if started != self._started:
-            self.started_cb.call(self, started)
-        self._started = started
-
-    def _get_started(self):
-        return self._started
-
-    added = property(_get_added, _set_added)
-    started = property(_get_started, _set_started)
-
-    def create(self):
-        """Save the log configuration in the Crazyflie"""
-        pk = CRTPPacket()
-        pk.set_header(5, CHAN_SETTINGS)
-        pk.data = (CMD_CREATE_BLOCK, self.id)
-        for var in self.variables:
-            if (var.is_toc_variable() is False):  # Memory location
-                logger.debug("Logging to raw memory %d, 0x%04X",
-                             var.get_storage_and_fetch_byte(), var.address)
-                pk.data.append(struct.pack('<B',
-                                           var.get_storage_and_fetch_byte()))
-                pk.data.append(struct.pack('<I', var.address))
-            else:  # Item in TOC
-                logger.debug("Adding %s with id=%d and type=0x%02X",
-                             var.name,
-                             self.cf.log.toc.get_element_id(
-                                 var.name), var.get_storage_and_fetch_byte())
-                pk.data.append(var.get_storage_and_fetch_byte())
-                pk.data.append(self.cf.log.toc.get_element_id(var.name))
-        logger.debug("Adding log block id {}".format(self.id))
-        self.cf.send_packet(pk, expected_reply=(CMD_CREATE_BLOCK, self.id))
-
-    def start(self):
-        """Start the logging for this entry"""
-        if (self.cf.link is not None):
-            if (self._added is False):
-                self.create()
-                logger.debug("First time block is started, add block")
-            else:
-                logger.debug("Block already registered, starting logging"
-                             " for id=%d", self.id)
-                pk = CRTPPacket()
-                pk.set_header(5, CHAN_SETTINGS)
-                pk.data = (CMD_START_LOGGING, self.id, self.period)
-                self.cf.send_packet(pk, expected_reply=(
-                    CMD_START_LOGGING, self.id))
-
-    def stop(self):
-        """Stop the logging for this entry"""
-        if (self.cf.link is not None):
-            if (self.id is None):
-                logger.warning("Stopping block, but no block registered")
-            else:
-                logger.debug("Sending stop logging for block id=%d", self.id)
-                pk = CRTPPacket()
-                pk.set_header(5, CHAN_SETTINGS)
-                pk.data = (CMD_STOP_LOGGING, self.id)
-                self.cf.send_packet(
-                    pk, expected_reply=(CMD_STOP_LOGGING, self.id))
-
-    def delete(self):
-        """Delete this entry in the Crazyflie"""
-        if (self.cf.link is not None):
-            if (self.id is None):
-                logger.warning("Delete block, but no block registered")
-            else:
-                logger.debug("LogEntry: Sending delete logging for block id=%d"
-                             % self.id)
-                pk = CRTPPacket()
-                pk.set_header(5, CHAN_SETTINGS)
-                pk.data = (CMD_DELETE_BLOCK, self.id)
-                self.cf.send_packet(
-                    pk, expected_reply=(CMD_DELETE_BLOCK, self.id))
-
-    def unpack_log_data(self, log_data, timestamp):
-        """Unpack received logging data so it represent real values according
-        to the configuration in the entry"""
-        ret_data = {}
-        data_index = 0
-        for var in self.variables:
-            size = LogTocElement.get_size_from_id(var.fetch_as)
-            name = var.name
-            unpackstring = LogTocElement.get_unpack_string_from_id(
-                var.fetch_as)
-            value = struct.unpack(
-                unpackstring, log_data[data_index:data_index + size])[0]
-            data_index += size
-            ret_data[name] = value
-        self.data_received_cb.call(timestamp, ret_data, self)
-
-
-class LogTocElement:
-    """An element in the Log TOC."""
-    types = {0x01: ("uint8_t", '<B', 1),
-             0x02: ("uint16_t", '<H', 2),
-             0x03: ("uint32_t", '<L', 4),
-             0x04: ("int8_t", '<b', 1),
-             0x05: ("int16_t", '<h', 2),
-             0x06: ("int32_t", '<i', 4),
-             0x08: ("FP16", '<h', 2),
-             0x07: ("float", '<f', 4)}
-
-    @staticmethod
-    def get_id_from_cstring(name):
-        """Return variable type id given the C-storage name"""
-        for key in list(LogTocElement.types.keys()):
-            if (LogTocElement.types[key][0] == name):
-                return key
-        raise KeyError("Type [%s] not found in LogTocElement.types!" % name)
-
-    @staticmethod
-    def get_cstring_from_id(ident):
-        """Return the C-storage name given the variable type id"""
-        try:
-            return LogTocElement.types[ident][0]
-        except KeyError:
-            raise KeyError("Type [%d] not found in LogTocElement.types"
-                           "!" % ident)
-
-    @staticmethod
-    def get_size_from_id(ident):
-        """Return the size in bytes given the variable type id"""
-        try:
-            return LogTocElement.types[ident][2]
-        except KeyError:
-            raise KeyError("Type [%d] not found in LogTocElement.types"
-                           "!" % ident)
-
-    @staticmethod
-    def get_unpack_string_from_id(ident):
-        """Return the Python unpack string given the variable type id"""
-        try:
-            return LogTocElement.types[ident][1]
-        except KeyError:
-            raise KeyError(
-                "Type [%d] not found in LogTocElement.types!" % ident)
-
-    def __init__(self, data=None):
-        """TocElement creator. Data is the binary payload of the element."""
-
-        if (data):
-            naming = data[2:]
-            zt = bytearray((0, ))
-            self.group = naming[:naming.find(zt)].decode("ISO-8859-1")
-            self.name = naming[naming.find(zt)+1:-1].decode("ISO-8859-1")
-
-            self.ident = data[0]
-
-            self.ctype = LogTocElement.get_cstring_from_id(data[1])
-            self.pytype = LogTocElement.get_unpack_string_from_id(data[1])
-
-            self.access = data[1] & 0x10
-
-
-class Log():
-    """Create log configuration"""
-
-    # These codes can be decoded using os.stderror, but
-    # some of the text messages will look very strange
-    # in the UI, so they are redefined here
-    _err_codes = {
-        errno.ENOMEM: "No more memory available",
-        errno.ENOEXEC: "Command not found",
-        errno.ENOENT: "No such block id",
-        errno.E2BIG: "Block too large",
-        errno.EEXIST: "Block already exists"
-    }
-
-    def __init__(self, crazyflie=None):
-        self.log_blocks = []
-        # Called with newly created blocks
-        self.block_added_cb = Caller()
-
-        self.cf = crazyflie
-        self.toc = None
-        self.cf.add_port_callback(CRTPPort.LOGGING, self._new_packet_cb)
-
-        self.toc_updated = Caller()
-        self.state = IDLE
-        self.fake_toc_crc = 0xDEADBEEF
-
-        self._refresh_callback = None
-        self._toc_cache = None
-
-    def add_config(self, logconf):
-        """Add a log configuration to the logging framework.
-
-        When doing this the contents of the log configuration will be validated
-        and listeners for new log configurations will be notified. When
-        validating the configuration the variables are checked against the TOC
-        to see that they actually exist. If they don't then the configuration
-        cannot be used. Since a valid TOC is required, a Crazyflie has to be
-        connected when calling this method, otherwise it will fail."""
-
-        if not self.cf.link:
-            logger.error("Cannot add configs without being connected to a "
-                         "Crazyflie!")
-            return
-
-        # If the log configuration contains variables that we added without
-        # type (i.e we want the stored as type for fetching as well) then
-        # resolve this now and add them to the block again.
-        for name in logconf.default_fetch_as:
-            var = self.toc.get_element_by_complete_name(name)
-            if not var:
-                logger.warning(
-                    "%s not in TOC, this block cannot be used!", name)
-                logconf.valid = False
-                raise KeyError("Variable {} not in TOC".format(name))
-            # Now that we know what type this variable has, add it to the log
-            # config again with the correct type
-            logconf.add_variable(name, var.ctype)
-
-        # Now check that all the added variables are in the TOC and that
-        # the total size constraint of a data packet with logging data is
-        # not
-        size = 0
-        for var in logconf.variables:
-            size += LogTocElement.get_size_from_id(var.fetch_as)
-            # Check that we are able to find the variable in the TOC so
-            # we can return error already now and not when the config is sent
-            if var.is_toc_variable():
-                if (self.toc.get_element_by_complete_name(var.name) is None):
-                    logger.warning(
-                        "Log: %s not in TOC, this block cannot be used!",
-                        var.name)
-                    logconf.valid = False
-                    raise KeyError("Variable {} not in TOC".format(var.name))
-
-        if (size <= MAX_LOG_DATA_PACKET_SIZE and
-                (logconf.period > 0 and logconf.period < 0xFF)):
-            logconf.valid = True
-            logconf.cf = self.cf
-            self.log_blocks.append(logconf)
-            self.block_added_cb.call(logconf)
-        else:
-            logconf.valid = False
-            raise AttributeError(
-                "The log configuration is too large or has an invalid "
-                "parameter")
-
-    def refresh_toc(self, refresh_done_callback, toc_cache):
-        """Start refreshing the table of loggale variables"""
-
-        self._toc_cache = toc_cache
-        self._refresh_callback = refresh_done_callback
-        self.toc = None
-
-        pk = CRTPPacket()
-        pk.set_header(CRTPPort.LOGGING, CHAN_SETTINGS)
-        pk.data = (CMD_RESET_LOGGING,)
-        self.cf.send_packet(pk, expected_reply=(CMD_RESET_LOGGING,))
-
-    def _find_block(self, id):
-        for block in self.log_blocks:
-            if block.id == id:
-                return block
-        return None
-
-    def _new_packet_cb(self, packet):
-        """Callback for newly arrived packets with TOC information"""
-        chan = packet.channel
-        cmd = packet.data[0]
-        payload = packet.data[1:]
-
-        if (chan == CHAN_SETTINGS):
-            id = payload[0]
-            error_status = payload[1]
-            block = self._find_block(id)
-            if (cmd == CMD_CREATE_BLOCK):
-                if (block is not None):
-                    if error_status == 0 or error_status == errno.EEXIST:
-                        if not block.added:
-                            logger.debug("Have successfully added id=%d", id)
-
-                            pk = CRTPPacket()
-                            pk.set_header(5, CHAN_SETTINGS)
-                            pk.data = (CMD_START_LOGGING, id, block.period)
-                            self.cf.send_packet(pk, expected_reply=(
-                                CMD_START_LOGGING, id))
-                            block.added = True
-                    else:
-                        msg = self._err_codes[error_status]
-                        logger.warning("Error %d when adding id=%d (%s)",
-                                       error_status, id, msg)
-                        block.err_no = error_status
-                        block.added_cb.call(False)
-                        block.error_cb.call(block, msg)
-
-                else:
-                    logger.warning("No LogEntry to assign block to !!!")
-            if (cmd == CMD_START_LOGGING):
-                if (error_status == 0x00):
-                    logger.info("Have successfully started logging for id=%d",
-                                id)
-                    if block:
-                        block.started = True
-
-                else:
-                    msg = self._err_codes[error_status]
-                    logger.warning("Error %d when starting id=%d (%s)",
-                                   error_status, id, msg)
-                    if block:
-                        block.err_no = error_status
-                        block.started_cb.call(self, False)
-                        # This is a temporary fix, we are adding a new issue
-                        # for this. For some reason we get an error back after
-                        # the block has been started and added. This will show
-                        # an error in the UI, but everything is still working.
-                        # block.error_cb.call(block, msg)
-
-            if (cmd == CMD_STOP_LOGGING):
-                if (error_status == 0x00):
-                    logger.info("Have successfully stopped logging for id=%d",
-                                id)
-                    if block:
-                        block.started = False
-
-            if (cmd == CMD_DELETE_BLOCK):
-                # Accept deletion of a block that isn't added. This could
-                # happen due to timing (i.e add/start/delete in fast sequence)
-                if error_status == 0x00 or error_status == errno.ENOENT:
-                    logger.info("Have successfully deleted id=%d", id)
-                    if block:
-                        block.started = False
-                        block.added = False
-
-            if (cmd == CMD_RESET_LOGGING):
-                # Guard against multiple responses due to re-sending
-                if not self.toc:
-                    logger.debug("Logging reset, continue with TOC download")
-                    self.log_blocks = []
-
-                    self.toc = Toc()
-                    toc_fetcher = TocFetcher(self.cf, LogTocElement,
-                                             CRTPPort.LOGGING,
-                                             self.toc, self._refresh_callback,
-                                             self._toc_cache)
-                    toc_fetcher.start()
-
-        if (chan == CHAN_LOGDATA):
-            chan = packet.channel
-            id = packet.data[0]
-            block = self._find_block(id)
-            timestamps = struct.unpack("<BBB", packet.data[1:4])
-            timestamp = (
-                timestamps[0] | timestamps[1] << 8 | timestamps[2] << 16)
-            logdata = packet.data[4:]
-            if (block is not None):
-                block.unpack_log_data(logdata, timestamp)
-            else:
-                logger.warning("Error no LogEntry to handle id=%d", id)
diff --git a/src/cflib/cflib/crazyflie/mem.py b/src/cflib/cflib/crazyflie/mem.py
deleted file mode 100644
index 7aae03b614dab8df79a927d9a81179e9ebef865f..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/mem.py
+++ /dev/null
@@ -1,843 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2014 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Enables flash access to the Crazyflie.
-
-"""
-
-import struct
-import errno
-import sys
-from threading import Lock
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
-from cflib.utils.callbacks import Caller
-from binascii import crc32
-import binascii
-import logging
-from functools import reduce
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Memory', 'MemoryElement']
-
-# Channels used for the logging port
-CHAN_INFO = 0
-CHAN_READ = 1
-CHAN_WRITE = 2
-
-# Commands used when accessing the Settings port
-CMD_INFO_VER = 0
-CMD_INFO_NBR = 1
-CMD_INFO_DETAILS = 2
-
-# The max size of a CRTP packet payload
-MAX_LOG_DATA_PACKET_SIZE = 30
-
-if sys.version_info < (3,):
-    EEPROM_TOKEN = "0xBC"
-else:
-    EEPROM_TOKEN = b"0xBC"
-
-logger = logging.getLogger(__name__)
-
-
-class MemoryElement(object):
-    """A memory """
-
-    TYPE_I2C = 0
-    TYPE_1W = 1
-    TYPE_DRIVER_LED = 0x10
-
-    def __init__(self, id, type, size, mem_handler):
-        """Initialize the element with default values"""
-        self.id = id
-        self.type = type
-        self.size = size
-        self.mem_handler = mem_handler
-
-    @staticmethod
-    def type_to_string(t):
-        """Get string representation of memory type"""
-        if t == MemoryElement.TYPE_I2C:
-            return "I2C"
-        if t == MemoryElement.TYPE_1W:
-            return "1-wire"
-        if t == MemoryElement.TYPE_DRIVER_LED:
-            return "LED driver"
-        return "Unknown"
-
-    def new_data(self, mem, addr, data):
-        logger.info("New data, but not OW mem")
-
-    def __str__(self):
-        """Generate debug string for memory"""
-        return ("Memory: id={}, type={}, size={}".format(
-            self.id, MemoryElement.type_to_string(self.type), self.size))
-
-
-class LED:
-    """Used to set color/intensity of one LED in the LED-ring"""
-
-    def __init__(self):
-        """Initialize to off"""
-        self.r = 0
-        self.g = 0
-        self.b = 0
-        self.intensity = 100
-
-    def set(self, r, g, b, intensity=None):
-        """Set the R/G/B and optionally intensity in one call"""
-        self.r = r
-        self.g = g
-        self.b = b
-        if intensity:
-            self.intensity = intensity
-
-
-class LEDDriverMemory(MemoryElement):
-    """Memory interface for using the LED-ring mapped memory for setting RGB
-       values for all the LEDs in the ring"""
-
-    def __init__(self, id, type, size, mem_handler):
-        """Initialize with 12 LEDs"""
-        super(LEDDriverMemory, self).__init__(id=id, type=type, size=size,
-                                              mem_handler=mem_handler)
-        self._update_finished_cb = None
-        self._write_finished_cb = None
-
-        self.leds = []
-        for i in range(12):
-            self.leds.append(LED())
-
-    def new_data(self, mem, addr, data):
-        """Callback for when new memory data has been fetched"""
-        if mem.id == self.id:
-            logger.info("Got new data from the LED driver, but we don't care.")
-
-    def write_data(self, write_finished_cb):
-        """Write the saved LED-ring data to the Crazyflie"""
-        self._write_finished_cb = write_finished_cb
-        data = bytearray()
-        for led in self.leds:
-            # In order to fit all the LEDs in one radio packet RGB565 is used
-            # to compress the colors. The calculations below converts 3 bytes
-            # RGB into 2 bytes RGB565. Then shifts the value of each color to
-            # LSB, applies the intensity and shifts them back for correct
-            # alignment on 2 bytes.
-            R5 = ((int)((((int(led.r) & 0xFF) * 249 + 1014) >> 11) & 0x1F) *
-                  led.intensity / 100)
-            G6 = ((int)((((int(led.g) & 0xFF) * 253 + 505) >> 10) & 0x3F) *
-                  led.intensity / 100)
-            B5 = ((int)((((int(led.b) & 0xFF) * 249 + 1014) >> 11) & 0x1F) *
-                  led.intensity / 100)
-            tmp = (int(R5) << 11) | (int(G6) << 5) | (int(B5) << 0)
-            data += bytearray((tmp >> 8, tmp & 0xFF))
-        self.mem_handler.write(self, 0x00, data, flush_queue=True)
-
-    def update(self, update_finished_cb):
-        """Request an update of the memory content"""
-        if not self._update_finished_cb:
-            self._update_finished_cb = update_finished_cb
-            self.valid = False
-            logger.info("Updating content of memory {}".format(self.id))
-            # Start reading the header
-            self.mem_handler.read(self, 0, 16)
-
-    def write_done(self, mem, addr):
-        if self._write_finished_cb and mem.id == self.id:
-            logger.info("Write to LED driver done")
-            self._write_finished_cb(self, addr)
-            self._write_finished_cb = None
-
-    def disconnect(self):
-        self._update_finished_cb = None
-        self._write_finished_cb = None
-
-
-class I2CElement(MemoryElement):
-    def __init__(self, id, type, size, mem_handler):
-        super(I2CElement, self).__init__(id=id, type=type, size=size,
-                                         mem_handler=mem_handler)
-        self._update_finished_cb = None
-        self._write_finished_cb = None
-        self.elements = {}
-        self.valid = False
-
-    def new_data(self, mem, addr, data):
-        """Callback for when new memory data has been fetched"""
-        if mem.id == self.id:
-            if addr == 0:
-                done = False
-                # Check for header
-                if data[0:4] == EEPROM_TOKEN:
-                    logger.info("Got new data: {}".format(data))
-                    [self.elements["version"],
-                     self.elements["radio_channel"],
-                     self.elements["radio_speed"],
-                     self.elements["pitch_trim"],
-                     self.elements["roll_trim"]] = struct.unpack("<BBBff",
-                                                                 data[4:15])
-                    if self.elements["version"] == 0:
-                        done = True
-                    elif self.elements["version"] == 1:
-                        self.datav0 = data
-                        self.mem_handler.read(self, 16, 5)
-                else:
-                    valid = False
-                    if self._update_finished_cb:
-                        self._update_finished_cb(self)
-                        self._update_finished_cb = None
-
-            if addr == 16:
-                [radio_address_upper, radio_address_lower] = struct.unpack(
-                    "<BI", self.datav0[15:16] + data[0:4])
-                self.elements["radio_address"] = int(
-                    radio_address_upper) << 32 | radio_address_lower
-
-                logger.info(self.elements)
-                data = self.datav0 + data
-                done = True
-
-            if done:
-                if self._checksum256(data[:len(data) - 1]) == \
-                        data[len(data) - 1]:
-                    self.valid = True
-                if self._update_finished_cb:
-                    self._update_finished_cb(self)
-                    self._update_finished_cb = None
-
-    def _checksum256(self, st):
-        return reduce(lambda x, y: x + y, list(st)) % 256
-
-    def write_data(self, write_finished_cb):
-        image = bytearray()
-        if self.elements["version"] == 0:
-            data = (
-                0x00, self.elements["radio_channel"],
-                self.elements["radio_speed"],
-                self.elements["pitch_trim"], self.elements["roll_trim"])
-            image += struct.pack("<BBBff", *data)
-        elif self.elements["version"] == 1:
-            data = (
-                0x01, self.elements["radio_channel"],
-                self.elements["radio_speed"],
-                self.elements["pitch_trim"], self.elements["roll_trim"],
-                self.elements["radio_address"] >> 32,
-                self.elements["radio_address"] & 0xFFFFFFFF)
-            image += struct.pack("<BBBffBI", *data)
-        # Adding some magic:
-        image = EEPROM_TOKEN + image
-        image += struct.pack("B", self._checksum256(image))
-
-        self._write_finished_cb = write_finished_cb
-
-        self.mem_handler.write(self, 0x00,
-                               struct.unpack("B" * len(image), image))
-
-    def update(self, update_finished_cb):
-        """Request an update of the memory content"""
-        if not self._update_finished_cb:
-            self._update_finished_cb = update_finished_cb
-            self.valid = False
-            logger.info("Updating content of memory {}".format(self.id))
-            # Start reading the header
-            self.mem_handler.read(self, 0, 16)
-
-    def write_done(self, mem, addr):
-        if self._write_finished_cb and mem.id == self.id:
-            self._write_finished_cb(self, addr)
-            self._write_finished_cb = None
-
-    def disconnect(self):
-        self._update_finished_cb = None
-        self._write_finished_cb = None
-
-
-class OWElement(MemoryElement):
-    """Memory class with extra functionality for 1-wire memories"""
-
-    element_mapping = {
-        1: "Board name",
-        2: "Board revision",
-        3: "Custom"
-    }
-
-    def __init__(self, id, type, size, addr, mem_handler):
-        """Initialize the memory with good defaults"""
-        super(OWElement, self).__init__(id=id, type=type, size=size,
-                                        mem_handler=mem_handler)
-        self.addr = addr
-
-        self.valid = False
-
-        self.vid = None
-        self.pid = None
-        self.name = None
-        self.pins = None
-        self.elements = {}
-
-        self._update_finished_cb = None
-        self._write_finished_cb = None
-
-        self._rev_element_mapping = {}
-        for key in list(OWElement.element_mapping.keys()):
-            self._rev_element_mapping[OWElement.element_mapping[key]] = key
-
-    def new_data(self, mem, addr, data):
-        """Callback for when new memory data has been fetched"""
-        if mem.id == self.id:
-            if addr == 0:
-                if self._parse_and_check_header(data[0:8]):
-                    if self._parse_and_check_elements(data[9:11]):
-                        self.valid = True
-                        self._update_finished_cb(self)
-                        self._update_finished_cb = None
-                    else:
-                        # We need to fetch the elements, find out the length
-                        (elem_ver, elem_len) = struct.unpack("BB", data[8:10])
-                        self.mem_handler.read(self, 8, elem_len + 3)
-                else:
-                    # Call the update if the CRC check of the header fails,
-                    # we're done here
-                    if self._update_finished_cb:
-                        self._update_finished_cb(self)
-                        self._update_finished_cb = None
-            elif addr == 0x08:
-                if self._parse_and_check_elements(data):
-                    self.valid = True
-                if self._update_finished_cb:
-                    self._update_finished_cb(self)
-                    self._update_finished_cb = None
-
-    def _parse_and_check_elements(self, data):
-        """
-        Parse and check the CRC and length of the elements part of the memory
-        """
-        (elem_ver, elem_len, crc) = (data[0], data[1], data[-1])
-        test_crc = crc32(data[:-1]) & 0x0ff
-        elem_data = data[2:-1]
-        if test_crc == crc:
-            while len(elem_data) > 0:
-                (eid, elen) = struct.unpack("BB", elem_data[:2])
-                self.elements[self.element_mapping[eid]] = \
-                    elem_data[2:2 + elen].decode("ISO-8859-1")
-                elem_data = elem_data[2 + elen:]
-            return True
-        return False
-
-    def write_done(self, mem, addr):
-        if self._write_finished_cb:
-            self._write_finished_cb(self, addr)
-            self._write_finished_cb = None
-
-    def write_data(self, write_finished_cb):
-        # First generate the header part
-        header_data = struct.pack("<BIBB", 0xEB, self.pins, self.vid, self.pid)
-        header_crc = crc32(header_data) & 0x0ff
-        header_data += struct.pack("B", header_crc)
-
-        # Now generate the elements part
-        elem = bytearray()
-        logger.info(list(self.elements.keys()))
-        for element in reversed(list(self.elements.keys())):
-            elem_string = self.elements[element]
-            # logger.info(">>>> {}".format(elem_string))
-            key_encoding = self._rev_element_mapping[element]
-            elem += struct.pack("BB", key_encoding, len(elem_string))
-            elem += bytearray(elem_string.encode("ISO-8859-1"))
-
-        elem_data = struct.pack("BB", 0x00, len(elem))
-        elem_data += elem
-        elem_crc = crc32(elem_data) & 0x0ff
-        elem_data += struct.pack("B", elem_crc)
-
-        data = header_data + elem_data
-
-        self.mem_handler.write(self, 0x00,
-                               struct.unpack("B" * len(data), data))
-
-        self._write_finished_cb = write_finished_cb
-
-    def update(self, update_finished_cb):
-        """Request an update of the memory content"""
-        if not self._update_finished_cb:
-            self._update_finished_cb = update_finished_cb
-            self.valid = False
-            logger.info("Updating content of memory {}".format(self.id))
-            # Start reading the header
-            self.mem_handler.read(self, 0, 11)
-
-    def _parse_and_check_header(self, data):
-        """Parse and check the CRC of the header part of the memory"""
-        # logger.info("Should parse header: {}".format(data))
-        (start, self.pins, self.vid, self.pid, crc) = struct.unpack("<BIBBB",
-                                                                    data)
-        test_crc = crc32(data[:-1]) & 0x0ff
-        if start == 0xEB and crc == test_crc:
-            return True
-        return False
-
-    def __str__(self):
-        """Generate debug string for memory"""
-        return ("OW {} ({:02X}:{:02X}): {}".format(
-            self.addr, self.vid, self.pid, self.elements))
-
-    def disconnect(self):
-        self._update_finished_cb = None
-        self._write_finished_cb = None
-
-
-class _ReadRequest:
-    """
-    Class used to handle memory reads that will split up the read in multiple
-    packets in necessary
-    """
-    MAX_DATA_LENGTH = 20
-
-    def __init__(self, mem, addr, length, cf):
-        """Initialize the object with good defaults"""
-        self.mem = mem
-        self.addr = addr
-        self._bytes_left = length
-        self.data = bytearray()
-        self.cf = cf
-
-        self._current_addr = addr
-
-    def start(self):
-        """Start the fetching of the data"""
-        self._request_new_chunk()
-
-    def resend(self):
-        logger.info("Sending write again...")
-        self._request_new_chunk()
-
-    def _request_new_chunk(self):
-        """
-        Called to request a new chunk of data to be read from the Crazyflie
-        """
-        # Figure out the length of the next request
-        new_len = self._bytes_left
-        if new_len > _ReadRequest.MAX_DATA_LENGTH:
-            new_len = _ReadRequest.MAX_DATA_LENGTH
-
-        logger.info("Requesting new chunk of {}bytes at 0x{:X}".format(
-            new_len, self._current_addr))
-
-        # Request the data for the next address
-        pk = CRTPPacket()
-        pk.set_header(CRTPPort.MEM, CHAN_READ)
-        pk.data = struct.pack("<BIB", self.mem.id, self._current_addr, new_len)
-        reply = struct.unpack("<BBBBB", pk.data[:-1])
-        self.cf.send_packet(pk, expected_reply=reply, timeout=1)
-
-    def add_data(self, addr, data):
-        """Callback when data is received from the Crazyflie"""
-        data_len = len(data)
-        if not addr == self._current_addr:
-            logger.warning(
-                "Address did not match when adding data to read request!")
-            return
-
-        # Add the data and calculate the next address to fetch
-        self.data += data
-        self._bytes_left -= data_len
-        self._current_addr += data_len
-
-        if self._bytes_left > 0:
-            self._request_new_chunk()
-            return False
-        else:
-            return True
-
-
-class _WriteRequest:
-    """
-    Class used to handle memory reads that will split up the read in multiple
-    packets in necessary
-    """
-    MAX_DATA_LENGTH = 25
-
-    def __init__(self, mem, addr, data, cf):
-        """Initialize the object with good defaults"""
-        self.mem = mem
-        self.addr = addr
-        self._bytes_left = len(data)
-        self._data = data
-        self.data = bytearray()
-        self.cf = cf
-
-        self._current_addr = addr
-
-        self._sent_packet = None
-        self._sent_reply = None
-
-        self._addr_add = 0
-
-    def start(self):
-        """Start the fetching of the data"""
-        self._write_new_chunk()
-
-    def resend(self):
-        logger.info("Sending write again...")
-        self.cf.send_packet(
-            self._sent_packet, expected_reply=self._sent_reply, timeout=1)
-
-    def _write_new_chunk(self):
-        """
-        Called to request a new chunk of data to be read from the Crazyflie
-        """
-        # Figure out the length of the next request
-        new_len = len(self._data)
-        if new_len > _WriteRequest.MAX_DATA_LENGTH:
-            new_len = _WriteRequest.MAX_DATA_LENGTH
-
-        logger.info("Writing new chunk of {}bytes at 0x{:X}".format(
-            new_len, self._current_addr))
-
-        data = self._data[:new_len]
-        self._data = self._data[new_len:]
-
-        pk = CRTPPacket()
-        pk.set_header(CRTPPort.MEM, CHAN_WRITE)
-        pk.data = struct.pack("<BI", self.mem.id, self._current_addr)
-        # Create a tuple used for matching the reply using id and address
-        reply = struct.unpack("<BBBBB", pk.data)
-        self._sent_reply = reply
-        # Add the data
-        pk.data += struct.pack("B" * len(data), *data)
-        self._sent_packet = pk
-        self.cf.send_packet(pk, expected_reply=reply, timeout=1)
-
-        self._addr_add = len(data)
-
-    def write_done(self, addr):
-        """Callback when data is received from the Crazyflie"""
-        if not addr == self._current_addr:
-            logger.warning(
-                "Address did not match when adding data to read request!")
-            return
-
-        if len(self._data) > 0:
-            self._current_addr += self._addr_add
-            self._write_new_chunk()
-            return False
-        else:
-            logger.info("This write request is done")
-            return True
-
-
-class Memory():
-    """Access memories on the Crazyflie"""
-
-    # These codes can be decoded using os.stderror, but
-    # some of the text messages will look very strange
-    # in the UI, so they are redefined here
-    _err_codes = {
-        errno.ENOMEM: "No more memory available",
-        errno.ENOEXEC: "Command not found",
-        errno.ENOENT: "No such block id",
-        errno.E2BIG: "Block too large",
-        errno.EEXIST: "Block already exists"
-    }
-
-    def __init__(self, crazyflie=None):
-        """Instantiate class and connect callbacks"""
-        self.mems = []
-        # Called when new memories have been added
-        self.mem_added_cb = Caller()
-        # Called when new data has been read
-        self.mem_read_cb = Caller()
-
-        self.mem_write_cb = Caller()
-
-        self.cf = crazyflie
-        self.cf.add_port_callback(CRTPPort.MEM, self._new_packet_cb)
-
-        self._refresh_callback = None
-        self._fetch_id = 0
-        self.nbr_of_mems = 0
-        self._ow_mem_fetch_index = 0
-        self._elem_data = ()
-        self._read_requests = {}
-        self._read_requests_lock = Lock()
-        self._write_requests = {}
-        self._write_requests_lock = Lock()
-        self._ow_mems_left_to_update = []
-
-        self._getting_count = False
-
-    def _mem_update_done(self, mem):
-        """
-        Callback from each individual memory (only 1-wire) when reading of
-        header/elements are done
-        """
-        if mem.id in self._ow_mems_left_to_update:
-            self._ow_mems_left_to_update.remove(mem.id)
-
-        logger.info(mem)
-
-        if len(self._ow_mems_left_to_update) == 0:
-            if self._refresh_callback:
-                self._refresh_callback()
-                self._refresh_callback = None
-
-    def get_mem(self, id):
-        """Fetch the memory with the supplied id"""
-        for m in self.mems:
-            if m.id == id:
-                return m
-
-        return None
-
-    def get_mems(self, type):
-        """Fetch all the memories of the supplied type"""
-        ret = ()
-        for m in self.mems:
-            if m.type == type:
-                ret += (m,)
-
-        return ret
-
-    def ow_search(self, vid=0xBC, pid=None, name=None):
-        """Search for specific memory id/name and return it"""
-        for m in self.get_mems(MemoryElement.TYPE_1W):
-            if pid and m.pid == pid or name and m.name == name:
-                return m
-
-        return None
-
-    def write(self, memory, addr, data, flush_queue=False):
-        """Write the specified data to the given memory at the given address"""
-        wreq = _WriteRequest(memory, addr, data, self.cf)
-        if memory.id not in self._write_requests:
-            self._write_requests[memory.id] = []
-
-        # Workaround until we secure the uplink and change messages for
-        # mems to non-blocking
-        self._write_requests_lock.acquire()
-        if flush_queue:
-            self._write_requests[memory.id] = self._write_requests[
-                memory.id][:1]
-        self._write_requests[memory.id].insert(len(self._write_requests), wreq)
-        if len(self._write_requests[memory.id]) == 1:
-            wreq.start()
-        self._write_requests_lock.release()
-
-        return True
-
-    def read(self, memory, addr, length):
-        """
-        Read the specified amount of bytes from the given memory at the given
-        address
-        """
-        if memory.id in self._read_requests:
-            logger.warning("There is already a read operation ongoing for "
-                           "memory id {}".format(memory.id))
-            return False
-
-        rreq = _ReadRequest(memory, addr, length, self.cf)
-        self._read_requests[memory.id] = rreq
-
-        rreq.start()
-
-        return True
-
-    def refresh(self, refresh_done_callback):
-        """Start fetching all the detected memories"""
-        self._refresh_callback = refresh_done_callback
-        self._fetch_id = 0
-        for m in self.mems:
-            try:
-                self.mem_read_cb.remove_callback(m.new_data)
-                m.disconnect()
-            except Exception as e:
-                logger.info(
-                    "Error when removing memory after update: {}".format(e))
-        self.mems = []
-
-        self.nbr_of_mems = 0
-        self._getting_count = False
-
-        logger.info("Requesting number of memories")
-        pk = CRTPPacket()
-        pk.set_header(CRTPPort.MEM, CHAN_INFO)
-        pk.data = (CMD_INFO_NBR,)
-        self.cf.send_packet(pk, expected_reply=(CMD_INFO_NBR,))
-
-    def _new_packet_cb(self, packet):
-        """Callback for newly arrived packets for the memory port"""
-        chan = packet.channel
-        cmd = packet.data[0]
-        payload = packet.data[1:]
-
-        if chan == CHAN_INFO:
-            if cmd == CMD_INFO_NBR:
-                self.nbr_of_mems = payload[0]
-                logger.info("{} memories found".format(self.nbr_of_mems))
-
-                # Start requesting information about the memories,
-                # if there are any...
-                if self.nbr_of_mems > 0:
-                    if not self._getting_count:
-                        self._getting_count = True
-                        logger.info("Requesting first id")
-                        pk = CRTPPacket()
-                        pk.set_header(CRTPPort.MEM, CHAN_INFO)
-                        pk.data = (CMD_INFO_DETAILS, 0)
-                        self.cf.send_packet(pk, expected_reply=(
-                            CMD_INFO_DETAILS, 0))
-                else:
-                    self._refresh_callback()
-
-            if cmd == CMD_INFO_DETAILS:
-
-                # Did we get a good reply, otherwise try again:
-                if len(payload) < 5:
-                    # Workaround for 1-wire bug when memory is detected
-                    # but updating the info crashes the communication with
-                    # the 1-wire. Fail by saying we only found 1 memory
-                    # (the I2C).
-                    logger.error(
-                        "-------->Got good count, but no info on mem!")
-                    self.nbr_of_mems = 1
-                    if self._refresh_callback:
-                        self._refresh_callback()
-                        self._refresh_callback = None
-                    return
-
-                # Create information about a new memory
-                # Id - 1 byte
-                mem_id = payload[0]
-                # Type - 1 byte
-                mem_type = payload[1]
-                # Size 4 bytes (as addr)
-                mem_size = struct.unpack("I", payload[2:6])[0]
-                # Addr (only valid for 1-wire?)
-                mem_addr_raw = struct.unpack("B" * 8, payload[6:14])
-                mem_addr = ""
-                for m in mem_addr_raw:
-                    mem_addr += "{:02X}".format(m)
-
-                if (not self.get_mem(mem_id)):
-                    if mem_type == MemoryElement.TYPE_1W:
-                        mem = OWElement(id=mem_id, type=mem_type,
-                                        size=mem_size,
-                                        addr=mem_addr, mem_handler=self)
-                        self.mem_read_cb.add_callback(mem.new_data)
-                        self.mem_write_cb.add_callback(mem.write_done)
-                        self._ow_mems_left_to_update.append(mem.id)
-                    elif mem_type == MemoryElement.TYPE_I2C:
-                        mem = I2CElement(id=mem_id, type=mem_type,
-                                         size=mem_size,
-                                         mem_handler=self)
-                        self.mem_read_cb.add_callback(mem.new_data)
-                        self.mem_write_cb.add_callback(mem.write_done)
-                    elif mem_type == MemoryElement.TYPE_DRIVER_LED:
-                        mem = LEDDriverMemory(id=mem_id, type=mem_type,
-                                              size=mem_size, mem_handler=self)
-                        logger.info(mem)
-                        self.mem_read_cb.add_callback(mem.new_data)
-                        self.mem_write_cb.add_callback(mem.write_done)
-                    else:
-                        mem = MemoryElement(id=mem_id, type=mem_type,
-                                            size=mem_size, mem_handler=self)
-                        logger.info(mem)
-                    self.mems.append(mem)
-                    self.mem_added_cb.call(mem)
-                    # logger.info(mem)
-
-                    self._fetch_id = mem_id + 1
-
-                if self.nbr_of_mems - 1 >= self._fetch_id:
-                    logger.info(
-                        "Requesting information about memory {}".format(
-                            self._fetch_id))
-                    pk = CRTPPacket()
-                    pk.set_header(CRTPPort.MEM, CHAN_INFO)
-                    pk.data = (CMD_INFO_DETAILS, self._fetch_id)
-                    self.cf.send_packet(pk, expected_reply=(
-                        CMD_INFO_DETAILS, self._fetch_id))
-                else:
-                    logger.info(
-                        "Done getting all the memories, start reading the OWs")
-                    ows = self.get_mems(MemoryElement.TYPE_1W)
-                    # If there are any OW mems start reading them, otherwise
-                    # we are done
-                    for ow_mem in self.get_mems(MemoryElement.TYPE_1W):
-                        ow_mem.update(self._mem_update_done)
-                    if len(self.get_mems(MemoryElement.TYPE_1W)) == 0:
-                        if self._refresh_callback:
-                            self._refresh_callback()
-                            self._refresh_callback = None
-
-        if chan == CHAN_WRITE:
-            id = cmd
-            (addr, status) = struct.unpack("<IB", payload[0:5])
-            logger.info(
-                "WRITE: Mem={}, addr=0x{:X}, status=0x{}".format(
-                    id, addr, status))
-            # Find the read request
-            if id in self._write_requests:
-                self._write_requests_lock.acquire()
-                wreq = self._write_requests[id][0]
-                if status == 0:
-                    if wreq.write_done(addr):
-                        # self._write_requests.pop(id, None)
-                        # Remove the first item
-                        self._write_requests[id].pop(0)
-                        self.mem_write_cb.call(wreq.mem, wreq.addr)
-
-                        # Get a new one to start (if there are any)
-                        if len(self._write_requests[id]) > 0:
-                            self._write_requests[id][0].start()
-
-                else:
-                    logger.info("Status {}: write resending...".format(status))
-                    wreq.resend()
-                self._write_requests_lock.release()
-
-        if chan == CHAN_READ:
-            id = cmd
-            (addr, status) = struct.unpack("<IB", payload[0:5])
-            data = struct.unpack("B" * len(payload[5:]), payload[5:])
-            logger.info("READ: Mem={}, addr=0x{:X}, status=0x{}, "
-                        "data={}".format(id, addr, status, data))
-            # Find the read request
-            if id in self._read_requests:
-                logger.info(
-                    "READING: We are still interested in request for "
-                    "mem {}".format(id))
-                rreq = self._read_requests[id]
-                if status == 0:
-                    if rreq.add_data(addr, payload[5:]):
-                        self._read_requests.pop(id, None)
-                        self.mem_read_cb.call(rreq.mem, rreq.addr, rreq.data)
-                else:
-                    logger.info("Status {}: resending...".format(status))
-                    rreq.resend()
diff --git a/src/cflib/cflib/crazyflie/param.py b/src/cflib/cflib/crazyflie/param.py
deleted file mode 100644
index 8dc77ca711d236da02bb51e6b6252570f8017c32..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/param.py
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Enables reading/writing of parameter values to/from the Crazyflie.
-
-When a Crazyflie is connected it's possible to download a TableOfContent of all
-the parameters that can be written/read.
-
-"""
-
-from cflib.utils.callbacks import Caller
-import struct
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
-from .toc import Toc, TocFetcher
-from threading import Thread, Lock
-import sys
-import logging
-if sys.version_info < (3,):
-    from Queue import Queue
-else:
-    from queue import Queue
-
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Param', 'ParamTocElement']
-
-logger = logging.getLogger(__name__)
-
-# Possible states
-IDLE = 0
-WAIT_TOC = 1
-WAIT_READ = 2
-WAIT_WRITE = 3
-
-TOC_CHANNEL = 0
-READ_CHANNEL = 1
-WRITE_CHANNEL = 2
-
-# TOC access command
-TOC_RESET = 0
-TOC_GETNEXT = 1
-TOC_GETCRC32 = 2
-
-
-# One element entry in the TOC
-class ParamTocElement:
-    """An element in the Log TOC."""
-
-    RW_ACCESS = 0
-    RO_ACCESS = 1
-
-    types = {0x08: ("uint8_t", '<B'),
-             0x09: ("uint16_t", '<H'),
-             0x0A: ("uint32_t", '<L'),
-             0x0B: ("uint64_t", '<Q'),
-             0x00: ("int8_t", '<b'),
-             0x01: ("int16_t", '<h'),
-             0x02: ("int32_t", '<i'),
-             0x03: ("int64_t", '<q'),
-             0x05: ("FP16", ''),
-             0x06: ("float", '<f'),
-             0x07: ("double", '<d')}
-
-    def __init__(self, data=None):
-        """TocElement creator. Data is the binary payload of the element."""
-        if (data):
-            strs = struct.unpack("s" * len(data[2:]), data[2:])
-            if sys.version_info < (3,):
-                strs = ("{}" * len(strs)).format(*strs).split("\0")
-            else:
-                s = ""
-                for ch in strs:
-                    s += ch.decode('ISO-8859-1')
-                strs = s.split("\x00")
-            self.group = strs[0]
-            self.name = strs[1]
-
-            if type(data[0]) == str:
-                self.ident = ord(data[0])
-            else:
-                self.ident = data[0]
-
-            metadata = data[1]
-            if type(metadata) == str:
-                metadata = ord(metadata)
-
-            self.ctype = self.types[metadata & 0x0F][0]
-            self.pytype = self.types[metadata & 0x0F][1]
-            if ((metadata & 0x40) != 0):
-                self.access = ParamTocElement.RO_ACCESS
-            else:
-                self.access = ParamTocElement.RW_ACCESS
-
-    def get_readable_access(self):
-        if (self.access == ParamTocElement.RO_ACCESS):
-            return "RO"
-        return "RW"
-
-
-class Param():
-    """
-    Used to read and write parameter values in the Crazyflie.
-    """
-
-    toc = Toc()
-
-    def __init__(self, crazyflie):
-        self.cf = crazyflie
-        self.param_update_callbacks = {}
-        self.group_update_callbacks = {}
-        self.all_update_callback = Caller()
-        self.param_updater = None
-
-        self.param_updater = _ParamUpdater(self.cf, self._param_updated)
-        self.param_updater.start()
-
-        self.cf.disconnected.add_callback(self._disconnected)
-
-        self.all_updated = Caller()
-        self.is_updated = False
-
-        self.values = {}
-
-    def request_update_of_all_params(self):
-        """Request an update of all the parameters in the TOC"""
-        for group in self.toc.toc:
-            for name in self.toc.toc[group]:
-                complete_name = "%s.%s" % (group, name)
-                self.request_param_update(complete_name)
-
-    def _check_if_all_updated(self):
-        """Check if all parameters from the TOC has at least been fetched
-        once"""
-        for g in self.toc.toc:
-            if g not in self.values:
-                return False
-            for n in self.toc.toc[g]:
-                if n not in self.values[g]:
-                    return False
-
-        return True
-
-    def _param_updated(self, pk):
-        """Callback with data for an updated parameter"""
-        var_id = pk.data[0]
-        element = self.toc.get_element_by_id(var_id)
-        if element:
-            s = struct.unpack(element.pytype, pk.data[1:])[0]
-            s = s.__str__()
-            complete_name = "%s.%s" % (element.group, element.name)
-
-            # Save the value for synchronous access
-            if element.group not in self.values:
-                self.values[element.group] = {}
-            self.values[element.group][element.name] = s
-
-            logger.debug("Updated parameter [%s]" % complete_name)
-            if complete_name in self.param_update_callbacks:
-                self.param_update_callbacks[complete_name].call(
-                    complete_name, s)
-            if element.group in self.group_update_callbacks:
-                self.group_update_callbacks[element.group].call(
-                    complete_name, s)
-            self.all_update_callback.call(complete_name, s)
-
-            # Once all the parameters are updated call the
-            # callback for "everything updated" (after all the param
-            # updated callbacks)
-            if self._check_if_all_updated() and not self.is_updated:
-                self.is_updated = True
-                self.all_updated.call()
-        else:
-            logger.debug("Variable id [%d] not found in TOC", var_id)
-
-    def remove_update_callback(self, group, name=None, cb=None):
-        """Remove the supplied callback for a group or a group.name"""
-        if not cb:
-            return
-
-        if not name:
-            if group in self.group_update_callbacks:
-                self.group_update_callbacks[group].remove_callback(cb)
-        else:
-            paramname = "{}.{}".format(group, name)
-            if paramname in self.param_update_callbacks:
-                self.param_update_callbacks[paramname].remove_callback(cb)
-
-    def add_update_callback(self, group=None, name=None, cb=None):
-        """
-        Add a callback for a specific parameter name. This callback will be
-        executed when a new value is read from the Crazyflie.
-        """
-        if not group and not name:
-            self.all_update_callback.add_callback(cb)
-        elif not name:
-            if group not in self.group_update_callbacks:
-                self.group_update_callbacks[group] = Caller()
-            self.group_update_callbacks[group].add_callback(cb)
-        else:
-            paramname = "{}.{}".format(group, name)
-            if paramname not in self.param_update_callbacks:
-                self.param_update_callbacks[paramname] = Caller()
-            self.param_update_callbacks[paramname].add_callback(cb)
-
-    def refresh_toc(self, refresh_done_callback, toc_cache):
-        """
-        Initiate a refresh of the parameter TOC.
-        """
-        toc_fetcher = TocFetcher(self.cf, ParamTocElement,
-                                 CRTPPort.PARAM, self.toc,
-                                 refresh_done_callback, toc_cache)
-        toc_fetcher.start()
-
-    def _disconnected(self, uri):
-        """Disconnected callback from Crazyflie API"""
-        self.param_updater.close()
-        self.is_updated = False
-        # Clear all values from the previous Crazyflie
-        self.toc = Toc()
-        self.values = {}
-
-    def request_param_update(self, complete_name):
-        """
-        Request an update of the value for the supplied parameter.
-        """
-        self.param_updater.request_param_update(
-            self.toc.get_element_id(complete_name))
-
-    def set_value(self, complete_name, value):
-        """
-        Set the value for the supplied parameter.
-        """
-        element = self.toc.get_element_by_complete_name(complete_name)
-
-        if not element:
-            logger.warning("Cannot set value for [%s], it's not in the TOC!",
-                           complete_name)
-            raise KeyError("{} not in param TOC".format(complete_name))
-        elif element.access == ParamTocElement.RO_ACCESS:
-            logger.debug("[%s] is read only, no trying to set value",
-                         complete_name)
-            raise AttributeError("{} is read-only!".format(complete_name))
-        else:
-            varid = element.ident
-            pk = CRTPPacket()
-            pk.set_header(CRTPPort.PARAM, WRITE_CHANNEL)
-            pk.data = struct.pack('<B', varid)
-            pk.data += struct.pack(element.pytype, eval(value))
-            self.param_updater.request_param_setvalue(pk)
-
-
-class _ParamUpdater(Thread):
-    """This thread will update params through a queue to make sure that we
-    get back values"""
-
-    def __init__(self, cf, updated_callback):
-        """Initialize the thread"""
-        Thread.__init__(self)
-        self.setDaemon(True)
-        self.wait_lock = Lock()
-        self.cf = cf
-        self.updated_callback = updated_callback
-        self.request_queue = Queue()
-        self.cf.add_port_callback(CRTPPort.PARAM, self._new_packet_cb)
-        self._should_close = False
-        self._req_param = -1
-
-    def close(self):
-        # First empty the queue from all packets
-        while not self.request_queue.empty():
-            self.request_queue.get()
-        # Then force an unlock of the mutex if we are waiting for a packet
-        # we didn't get back due to a disconnect for example.
-        try:
-            self.wait_lock.release()
-        except:
-            pass
-
-    def request_param_setvalue(self, pk):
-        """Place a param set value request on the queue. When this is sent to
-        the Crazyflie it will answer with the update param value. """
-        self.request_queue.put(pk)
-
-    def _new_packet_cb(self, pk):
-        """Callback for newly arrived packets"""
-        if pk.channel == READ_CHANNEL or pk.channel == WRITE_CHANNEL:
-            var_id = pk.data[0]
-            if (pk.channel != TOC_CHANNEL and self._req_param == var_id and
-                    pk is not None):
-                self.updated_callback(pk)
-                self._req_param = -1
-                try:
-                    self.wait_lock.release()
-                except:
-                    pass
-
-    def request_param_update(self, var_id):
-        """Place a param update request on the queue"""
-        pk = CRTPPacket()
-        pk.set_header(CRTPPort.PARAM, READ_CHANNEL)
-        pk.data = struct.pack('<B', var_id)
-        logger.debug("Requesting request to update param [%d]", var_id)
-        self.request_queue.put(pk)
-
-    def run(self):
-        while not self._should_close:
-            pk = self.request_queue.get()  # Wait for request update
-            self.wait_lock.acquire()
-            if self.cf.link:
-                self._req_param = pk.data[0]
-                self.cf.send_packet(pk, expected_reply=(tuple(pk.data[0:2])))
-            else:
-                self.wait_lock.release()
diff --git a/src/cflib/cflib/crazyflie/platformservice.py b/src/cflib/cflib/crazyflie/platformservice.py
deleted file mode 100644
index 10abdc252ad9c5c32433b155fdbdbc470cb53e8e..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/platformservice.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Used for sending control setpoints to the Crazyflie
-"""
-
-from cflib.crtp.crtpstack import CRTPPacket, CRTPPort
-import struct
-
-__author__ = 'Bitcraze AB'
-__all__ = ['PlatformService']
-
-
-class PlatformService():
-    """
-    Used for sending control setpoints to the Crazyflie
-    """
-
-    def __init__(self, crazyflie=None):
-        """
-        Initialize the platform object.
-        """
-        self._cf = crazyflie
-
-    def set_continous_wave(self, enabled):
-        """
-        Enable/disable the client side X-mode. When enabled this recalculates
-        the setpoints before sending them to the Crazyflie.
-        """
-        pk = CRTPPacket()
-        pk.set_header(CRTPPort.PLATFORM, 0)
-        pk.data = (0, enabled)
-        self._cf.send_packet(pk)
diff --git a/src/cflib/cflib/crazyflie/toc.py b/src/cflib/cflib/crazyflie/toc.py
deleted file mode 100644
index 984e93ebaaf5d528ee4f1f102ad8c68b17fa434f..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/toc.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-A generic TableOfContents module that is used to fetch, store and minipulate
-a TOC for logging or parameters.
-"""
-
-from cflib.crtp.crtpstack import CRTPPacket
-import struct
-
-import logging
-
-__author__ = 'Bitcraze AB'
-__all__ = ['TocElement', 'Toc', 'TocFetcher']
-
-logger = logging.getLogger(__name__)
-
-TOC_CHANNEL = 0
-
-# Commands used when accessing the Table of Contents
-CMD_TOC_ELEMENT = 0
-CMD_TOC_INFO = 1
-
-# Possible states when receiving TOC
-IDLE = "IDLE"
-GET_TOC_INFO = "GET_TOC_INFO"
-GET_TOC_ELEMENT = "GET_TOC_ELEMENT"
-
-
-class TocElement:
-    """An element in the TOC."""
-    RW_ACCESS = 0
-    RO_ACCESS = 1
-
-    ident = 0
-    group = ""
-    name = ""
-    ctype = ""
-    pytype = ""
-    access = RO_ACCESS
-
-
-class Toc:
-    """Container for TocElements."""
-
-    def __init__(self):
-        self.toc = {}
-
-    def clear(self):
-        """Clear the TOC"""
-        self.toc = {}
-
-    def add_element(self, element):
-        """Add a new TocElement to the TOC container."""
-        try:
-            self.toc[element.group][element.name] = element
-        except KeyError:
-            self.toc[element.group] = {}
-            self.toc[element.group][element.name] = element
-
-    def get_element_by_complete_name(self, complete_name):
-        """Get a TocElement element identified by complete name from the
-        container."""
-        try:
-            return self.get_element_by_id(self.get_element_id(complete_name))
-        except ValueError:
-            # Item not found
-            return None
-
-    def get_element_id(self, complete_name):
-        """Get the TocElement element id-number of the element with the
-        supplied name."""
-        [group, name] = complete_name.split(".")
-        element = self.get_element(group, name)
-        if element:
-            return element.ident
-        else:
-            logger.warning("Unable to find variable [%s]", complete_name)
-            return None
-
-    def get_element(self, group, name):
-        """Get a TocElement element identified by name and group from the
-        container."""
-        try:
-            return self.toc[group][name]
-        except KeyError:
-            return None
-
-    def get_element_by_id(self, ident):
-        """Get a TocElement element identified by index number from the
-        container."""
-        for group in list(self.toc.keys()):
-            for name in list(self.toc[group].keys()):
-                if self.toc[group][name].ident == ident:
-                    return self.toc[group][name]
-        return None
-
-
-class TocFetcher:
-    """Fetches TOC entries from the Crazyflie"""
-
-    def __init__(self, crazyflie, element_class, port, toc_holder,
-                 finished_callback, toc_cache):
-        self.cf = crazyflie
-        self.port = port
-        self._crc = 0
-        self.requested_index = None
-        self.nbr_of_items = None
-        self.state = None
-        self.toc = toc_holder
-        self._toc_cache = toc_cache
-        self.finished_callback = finished_callback
-        self.element_class = element_class
-
-    def start(self):
-        """Initiate fetching of the TOC."""
-        logger.debug("[%d]: Start fetching...", self.port)
-        # Register callback in this class for the port
-        self.cf.add_port_callback(self.port, self._new_packet_cb)
-
-        # Request the TOC CRC
-        self.state = GET_TOC_INFO
-        pk = CRTPPacket()
-        pk.set_header(self.port, TOC_CHANNEL)
-        pk.data = (CMD_TOC_INFO,)
-        self.cf.send_packet(pk, expected_reply=(CMD_TOC_INFO,))
-
-    def _toc_fetch_finished(self):
-        """Callback for when the TOC fetching is finished"""
-        self.cf.remove_port_callback(self.port, self._new_packet_cb)
-        logger.debug("[%d]: Done!", self.port)
-        self.finished_callback()
-
-    def _new_packet_cb(self, packet):
-        """Handle a newly arrived packet"""
-        chan = packet.channel
-        if (chan != 0):
-            return
-        payload = packet.data[1:]
-
-        if (self.state == GET_TOC_INFO):
-            [self.nbr_of_items, self._crc] = struct.unpack("<BI", payload[:5])
-            logger.debug("[%d]: Got TOC CRC, %d items and crc=0x%08X",
-                         self.port, self.nbr_of_items, self._crc)
-
-            cache_data = self._toc_cache.fetch(self._crc)
-            if (cache_data):
-                self.toc.toc = cache_data
-                logger.info("TOC for port [%s] found in cache" % self.port)
-                self._toc_fetch_finished()
-            else:
-                self.state = GET_TOC_ELEMENT
-                self.requested_index = 0
-                self._request_toc_element(self.requested_index)
-
-        elif (self.state == GET_TOC_ELEMENT):
-            # Always add new element, but only request new if it's not the
-            # last one.
-            if self.requested_index != payload[0]:
-                return
-            self.toc.add_element(self.element_class(payload))
-            logger.debug("Added element [%s]",
-                         self.element_class(payload).ident)
-            if (self.requested_index < (self.nbr_of_items - 1)):
-                logger.debug("[%d]: More variables, requesting index %d",
-                             self.port, self.requested_index + 1)
-                self.requested_index = self.requested_index + 1
-                self._request_toc_element(self.requested_index)
-            else:  # No more variables in TOC
-                self._toc_cache.insert(self._crc, self.toc.toc)
-                self._toc_fetch_finished()
-
-    def _request_toc_element(self, index):
-        """Request information about a specific item in the TOC"""
-        logger.debug("Requesting index %d on port %d", index, self.port)
-        pk = CRTPPacket()
-        pk.set_header(self.port, TOC_CHANNEL)
-        pk.data = (CMD_TOC_ELEMENT, index)
-        self.cf.send_packet(pk, expected_reply=(CMD_TOC_ELEMENT, index))
diff --git a/src/cflib/cflib/crazyflie/toccache.py b/src/cflib/cflib/crazyflie/toccache.py
deleted file mode 100644
index 22add3c8ea979e3e9352badd2ca5f77b5026cda7..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crazyflie/toccache.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Access the TOC cache for reading/writing. It supports both user
-cache and dist cache.
-"""
-
-import os
-import json
-from glob import glob
-
-import logging
-
-from .log import LogTocElement  # pylint: disable=W0611
-from .param import ParamTocElement  # pylint: disable=W0611
-
-__author__ = 'Bitcraze AB'
-__all__ = ['TocCache']
-
-logger = logging.getLogger(__name__)
-
-
-class TocCache():
-    """
-    Access to TOC cache. To turn of the cache functionality
-    don't supply any directories.
-    """
-
-    def __init__(self, ro_cache=None, rw_cache=None):
-        self._cache_files = []
-        if (ro_cache):
-            self._cache_files += glob(ro_cache + "/*.json")
-        if (rw_cache):
-            self._cache_files += glob(rw_cache + "/*.json")
-            if not os.path.exists(rw_cache):
-                os.makedirs(rw_cache)
-
-        self._rw_cache = rw_cache
-
-    def fetch(self, crc):
-        """ Try to get a hit in the cache, return None otherwise """
-        cache_data = None
-        pattern = "%08X.json" % crc
-        hit = None
-
-        for name in self._cache_files:
-            if (name.endswith(pattern)):
-                hit = name
-
-        if (hit):
-            try:
-                cache = open(hit)
-                cache_data = json.load(cache,
-                                       object_hook=self._decoder)
-                cache.close()
-            except Exception as exp:
-                logger.warning("Error while parsing cache file [%s]:%s",
-                               hit, str(exp))
-
-        return cache_data
-
-    def insert(self, crc, toc):
-        """ Save a new cache to file """
-        if self._rw_cache:
-            try:
-                filename = "%s/%08X.json" % (self._rw_cache, crc)
-                cache = open(filename, 'w')
-                cache.write(json.dumps(toc, indent=2,
-                                       default=self._encoder))
-                cache.close()
-                logger.info("Saved cache to [%s]", filename)
-                self._cache_files += [filename]
-            except Exception as exp:
-                logger.warning("Could not save cache to file [%s]: %s",
-                               filename, str(exp))
-        else:
-            logger.warning("Could not save cache, no writable directory")
-
-    def _encoder(self, obj):
-        """ Encode a toc element leaf-node """
-        return {'__class__': obj.__class__.__name__,
-                'ident': obj.ident,
-                'group': obj.group,
-                'name': obj.name,
-                'ctype': obj.ctype,
-                'pytype': obj.pytype,
-                'access': obj.access}
-        raise TypeError(repr(obj) + ' is not JSON serializable')
-
-    def _decoder(self, obj):
-        """ Decode a toc element leaf-node """
-        if '__class__' in obj:
-            elem = eval(obj['__class__'])()
-            elem.ident = obj['ident']
-            elem.group = str(obj['group'])
-            elem.name = str(obj['name'])
-            elem.ctype = str(obj['ctype'])
-            elem.pytype = str(obj['pytype'])
-            elem.access = obj['access']
-            return elem
-        return obj
diff --git a/src/cflib/cflib/crtp/__init__.py b/src/cflib/cflib/crtp/__init__.py
deleted file mode 100644
index 0624614b03b043d1bf3a5a72b5945c23578f330e..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/__init__.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""Scans and creates communication interfaces."""
-
-import logging
-
-from .radiodriver import RadioDriver
-from .udpdriver import UdpDriver
-from .serialdriver import SerialDriver
-from .debugdriver import DebugDriver
-from .usbdriver import UsbDriver
-from .exceptions import WrongUriType
-
-__author__ = 'Bitcraze AB'
-__all__ = []
-
-logger = logging.getLogger(__name__)
-
-
-DRIVERS = [RadioDriver, SerialDriver, UdpDriver, DebugDriver, UsbDriver]
-INSTANCES = []
-
-
-def init_drivers(enable_debug_driver=False):
-    """Initialize all the drivers."""
-    for driver in DRIVERS:
-        try:
-            if driver != DebugDriver or enable_debug_driver:
-                INSTANCES.append(driver())
-        except Exception:  # pylint: disable=W0703
-            continue
-
-
-def scan_interfaces(address=None):
-    """ Scan all the interfaces for available Crazyflies """
-    available = []
-    found = []
-    for instance in INSTANCES:
-        logger.debug("Scanning: %s", instance)
-        try:
-            found = instance.scan_interface(address)
-            available += found
-        except Exception:
-            raise
-    return available
-
-
-def get_interfaces_status():
-    """Get the status of all the interfaces"""
-    status = {}
-    for instance in INSTANCES:
-        try:
-            status[instance.get_name()] = instance.get_status()
-        except Exception:
-            raise
-    return status
-
-
-def get_link_driver(uri, link_quality_callback=None, link_error_callback=None):
-    """Return the link driver for the given URI. Returns None if no driver
-    was found for the URI or the URI was not well formatted for the matching
-    driver."""
-    for instance in INSTANCES:
-        try:
-            instance.connect(uri, link_quality_callback, link_error_callback)
-            return instance
-        except WrongUriType:
-            continue
-
-    return None
diff --git a/src/cflib/cflib/crtp/crtpdriver.py b/src/cflib/cflib/crtp/crtpdriver.py
deleted file mode 100644
index 246f8d3ed0130dfbbadeee4dadd435ed0c1e091c..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/crtpdriver.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-CRTP Driver main class.
-"""
-
-__author__ = 'Bitcraze AB'
-__all__ = ['CRTPDriver']
-
-
-class CRTPDriver:
-    """ CTRP Driver main class
-
-    This class in inherited by all the CRTP link drivers.
-    """
-
-    def __init__(self):
-        """Driver constructor. Throw an exception if the driver is unable to
-        open the URI
-        """
-        self.needs_resending = True
-
-    def connect(self, uri, link_quality_callback, link_error_callback):
-        """Connect the driver to a specified URI
-
-        @param uri Uri of the link to open
-        @param link_quality_callback Callback to report link quality in percent
-        @param link_error_callback Callback to report errors (will result in
-               disconnection)
-        """
-
-    def send_packet(self, pk):
-        """Send a CRTP packet"""
-
-    def receive_packet(self, wait=0):
-        """Receive a CRTP packet.
-
-        @param wait The time to wait for a packet in second. -1 means forever
-
-        @return One CRTP packet or None if no packet has been received.
-        """
-
-    def get_status(self):
-        """
-        Return a status string from the interface.
-        """
-
-    def get_name(self):
-        """
-        Return a human readable name of the interface.
-        """
-
-    def scan_interface(self, address=None):
-        """
-        Scan interface for available Crazyflie quadcopters and return a list
-        with them.
-        """
-
-    def enum(self):
-        """Enumerate, and return a list, of the available link URI on this
-        system
-        """
-
-    def get_help(self):
-        """return the help message on how to form the URI for this driver
-        None means no help
-        """
-
-    def close(self):
-        """Close the link"""
diff --git a/src/cflib/cflib/crtp/crtpstack.py b/src/cflib/cflib/crtp/crtpstack.py
deleted file mode 100644
index dc46ccd5209552bddf06a18e21219e7865c14be9..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/crtpstack.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-CRTP packet and ports.
-"""
-
-import sys
-import logging
-
-__author__ = 'Bitcraze AB'
-__all__ = ['CRTPPort', 'CRTPPacket']
-
-logger = logging.getLogger(__name__)
-
-
-class CRTPPort:
-    """
-    Lists the available ports for the CRTP.
-    """
-    CONSOLE = 0x00
-    PARAM = 0x02
-    COMMANDER = 0x03
-    MEM = 0x04
-    LOGGING = 0x05
-    DEBUGDRIVER = 0x0E
-    LINKCTRL = 0x0F
-    ALL = 0xFF
-
-
-class CRTPPacket(object):
-    """
-    A packet that can be sent via the CRTP.
-    """
-
-    def __init__(self, header=0, data=None):
-        """
-        Create an empty packet with default values.
-        """
-        self.size = 0
-        self._data = bytearray()
-        # The two bits in position 3 and 4 needs to be set for legacy
-        # support of the bootloader
-        self.header = header | 0x3 << 2
-        self._port = (header & 0xF0) >> 4
-        self._channel = header & 0x03
-        if data:
-            self._set_data(data)
-
-    def _get_channel(self):
-        """Get the packet channel"""
-        return self._channel
-
-    def _set_channel(self, channel):
-        """Set the packet channel"""
-        self._channel = channel
-        self._update_header()
-
-    def _get_port(self):
-        """Get the packet port"""
-        return self._port
-
-    def _set_port(self, port):
-        """Set the packet port"""
-        self._port = port
-        self._update_header()
-
-    def get_header(self):
-        """Get the header"""
-        self._update_header()
-        return self.header
-
-    def set_header(self, port, channel):
-        """
-        Set the port and channel for this packet.
-        """
-        self._port = port
-        self.channel = channel
-        self._update_header()
-
-    def _update_header(self):
-        """Update the header with the port/channel values"""
-        # The two bits in position 3 and 4 needs to be set for legacy
-        # support of the bootloader
-        self.header = ((self._port & 0x0f) << 4 | 3 << 2 |
-                       (self.channel & 0x03))
-
-    # Some python madness to access different format of the data
-    def _get_data(self):
-        """Get the packet data"""
-        return self._data
-
-    def _set_data(self, data):
-        """Set the packet data"""
-        if type(data) == bytearray:
-            self._data = data
-        elif type(data) == str:
-            if sys.version_info < (3,):
-                self._data = bytearray(data)
-            else:
-                self._data = bytearray(data.encode('ISO-8859-1'))
-        elif type(data) == list or type(data) == tuple:
-            self._data = bytearray(data)
-        elif sys.version_info >= (3,) and type(data) == bytes:
-            self._data = bytearray(data)
-        else:
-            raise Exception("Data must be bytearray, string, list or tuple,"
-                            " not {}".format(type(data)))
-
-    def _get_data_l(self):
-        """Get the data in the packet as a list"""
-        return list(self._get_data_t())
-
-    def _get_data_t(self):
-        """Get the data in the packet as a tuple"""
-        return tuple(self._data)
-
-    def __str__(self):
-        """Get a string representation of the packet"""
-        return "{}:{} {}".format(self._port, self.channel, self.datat)
-
-    data = property(_get_data, _set_data)
-    datal = property(_get_data_l, _set_data)
-    datat = property(_get_data_t, _set_data)
-    datas = property(_get_data, _set_data)
-    port = property(_get_port, _set_port)
-    channel = property(_get_channel, _set_channel)
diff --git a/src/cflib/cflib/crtp/debugdriver.py b/src/cflib/cflib/crtp/debugdriver.py
deleted file mode 100644
index 4bfcc5da6f8f9b8c8158c1cd1f4e042102e8a06e..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/debugdriver.py
+++ /dev/null
@@ -1,898 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Fake link driver used to debug the UI without using the Crazyflie.
-
-The operation of this driver can be controlled in two ways, either by
-connecting to different URIs or by sending messages to the DebugDriver port
-though CRTP once connected.
-
-For normal connections a console thread is also started that will send
-generated console output via CRTP.
-"""
-
-from threading import Thread
-from .crtpdriver import CRTPDriver
-from .crtpstack import CRTPPacket, CRTPPort
-from .exceptions import WrongUriType
-import sys
-import re
-import time
-import struct
-from datetime import datetime
-from cflib.crazyflie.log import LogTocElement
-from cflib.crazyflie.param import ParamTocElement
-import random
-import string
-import errno
-
-import logging
-if sys.version_info < (3,):
-    import Queue as queue
-else:
-    import queue
-
-__author__ = 'Bitcraze AB'
-__all__ = ['DebugDriver']
-
-logger = logging.getLogger(__name__)
-
-# This setup is used to debug raw memory logging
-memlogging = {0x01: {"min": 0, "max": 255, "mod": 1, "vartype": 1},
-              0x02: {"min": 0, "max": 65000, "mod": 100, "vartype": 2},
-              0x03: {"min": 0, "max": 100000, "mod": 1000, "vartype": 3},
-              0x04: {"min": -100, "max": 100, "mod": 1, "vartype": 4},
-              0x05: {"min": -10000, "max": 10000, "mod": 2000, "vartype": 5},
-              0x06: {"min": -50000, "max": 50000, "mod": 1000, "vartype": 6},
-              0x07: {"min": 0, "max": 255, "mod": 1, "vartype": 1}}
-
-
-class FakeMemory:
-    TYPE_I2C = 0
-    TYPE_1W = 1
-
-    def __init__(self, type, size, addr, data=None):
-        self.type = type
-        self.size = size
-        self.addr = addr
-        self.data = [0] * size
-        if data:
-            for i in range(len(data)):
-                self.data[i] = data[i]
-
-    def erase(self):
-        self.data = [0] * self.size
-
-
-class DebugDriver(CRTPDriver):
-    """ Debug driver used for debugging UI/communication without using a
-    Crazyflie"""
-
-    def __init__(self):
-        self.fakeLoggingThreads = []
-        self._fake_mems = []
-        self.needs_resending = False
-        # Fill up the fake logging TOC with values and data
-        self.fakeLogToc = []
-        self.fakeLogToc.append({"varid": 0, "vartype": 5, "vargroup": "imu",
-                                "varname": "gyro_x", "min": -10000,
-                                "max": 10000, "mod": 1000})
-        self.fakeLogToc.append({"varid": 1, "vartype": 5, "vargroup": "imu",
-                                "varname": "gyro_y", "min": -10000,
-                                "max": 10000, "mod": 150})
-        self.fakeLogToc.append({"varid": 2, "vartype": 5, "vargroup": "imu",
-                                "varname": "gyro_z", "min": -10000,
-                                "max": 10000, "mod": 200})
-        self.fakeLogToc.append({"varid": 3, "vartype": 5, "vargroup": "imu",
-                                "varname": "acc_x", "min": -1000,
-                                "max": 1000, "mod": 15})
-        self.fakeLogToc.append({"varid": 4, "vartype": 5, "vargroup": "imu",
-                                "varname": "acc_y", "min": -1000,
-                                "max": 1000, "mod": 10})
-        self.fakeLogToc.append({"varid": 5, "vartype": 5, "vargroup": "imu",
-                                "varname": "acc_z", "min": -1000,
-                                "max": 1000, "mod": 20})
-        self.fakeLogToc.append({"varid": 6, "vartype": 7,
-                                "vargroup": "stabilizer", "varname": "roll",
-                                "min": -90, "max": 90, "mod": 2})
-        self.fakeLogToc.append({"varid": 7, "vartype": 7,
-                                "vargroup": "stabilizer", "varname": "pitch",
-                                "min": -90, "max": 90, "mod": 1.5})
-        self.fakeLogToc.append({"varid": 8, "vartype": 7,
-                                "vargroup": "stabilizer", "varname": "yaw",
-                                "min": -90, "max": 90, "mod": 2.5})
-        self.fakeLogToc.append({"varid": 9, "vartype": 7, "vargroup": "pm",
-                                "varname": "vbat", "min": 3.0,
-                                "max": 4.2, "mod": 0.1})
-        self.fakeLogToc.append({"varid": 10, "vartype": 6, "vargroup": "motor",
-                                "varname": "m1", "min": 0, "max": 65000,
-                                "mod": 1000})
-        self.fakeLogToc.append({"varid": 11, "vartype": 6, "vargroup": "motor",
-                                "varname": "m2", "min": 0, "max": 65000,
-                                "mod": 1000})
-        self.fakeLogToc.append({"varid": 12, "vartype": 6, "vargroup": "motor",
-                                "varname": "m3", "min": 0, "max": 65000,
-                                "mod": 1000})
-        self.fakeLogToc.append({"varid": 13, "vartype": 6, "vargroup": "motor",
-                                "varname": "m4", "min": 0, "max": 65000,
-                                "mod": 1000})
-        self.fakeLogToc.append({"varid": 14, "vartype": 2,
-                                "vargroup": "stabilizer", "varname": "thrust",
-                                "min": 0, "max": 65000, "mod": 1000})
-        self.fakeLogToc.append({"varid": 15, "vartype": 7,
-                                "vargroup": "baro", "varname": "asl",
-                                "min": 540, "max": 545, "mod": 0.5})
-        self.fakeLogToc.append({"varid": 16, "vartype": 7,
-                                "vargroup": "baro", "varname": "aslRaw",
-                                "min": 540, "max": 545, "mod": 1.0})
-        self.fakeLogToc.append({"varid": 17, "vartype": 7,
-                                "vargroup": "baro", "varname": "aslLong",
-                                "min": 540, "max": 545, "mod": 0.5})
-        self.fakeLogToc.append({"varid": 18, "vartype": 7,
-                                "vargroup": "baro", "varname": "temp",
-                                "min": 26, "max": 38, "mod": 1.0})
-        self.fakeLogToc.append({"varid": 19, "vartype": 7,
-                                "vargroup": "altHold", "varname": "target",
-                                "min": 542, "max": 543, "mod": 0.1})
-        self.fakeLogToc.append({"varid": 20, "vartype": 6,
-                                "vargroup": "gps", "varname": "lat",
-                                "min": 556112190, "max": 556112790,
-                                "mod": 10})
-        self.fakeLogToc.append({"varid": 21, "vartype": 6,
-                                "vargroup": "gps", "varname": "lon",
-                                "min": 129945110, "max": 129945710,
-                                "mod": 10})
-        self.fakeLogToc.append({"varid": 22, "vartype": 6,
-                                "vargroup": "gps", "varname": "hMSL",
-                                "min": 0, "max": 100000,
-                                "mod": 1000})
-        self.fakeLogToc.append({"varid": 23, "vartype": 6,
-                                "vargroup": "gps", "varname": "heading",
-                                "min": -10000000, "max": 10000000,
-                                "mod": 100000})
-        self.fakeLogToc.append({"varid": 24, "vartype": 6,
-                                "vargroup": "gps", "varname": "gSpeed",
-                                "min": 0, "max": 1000,
-                                "mod": 100})
-        self.fakeLogToc.append({"varid": 25, "vartype": 3,
-                                "vargroup": "gps", "varname": "hAcc",
-                                "min": 0, "max": 5000,
-                                "mod": 100})
-        self.fakeLogToc.append({"varid": 26, "vartype": 1,
-                                "vargroup": "gps", "varname": "fixType",
-                                "min": 0, "max": 5,
-                                "mod": 1})
-
-        # Fill up the fake logging TOC with values and data
-        self.fakeParamToc = []
-        self.fakeParamToc.append({"varid": 0, "vartype": 0x08,
-                                  "vargroup": "blah", "varname": "p",
-                                  "writable": True, "value": 100})
-        self.fakeParamToc.append({"varid": 1, "vartype": 0x0A,
-                                  "vargroup": "info", "varname": "cid",
-                                  "writable": False, "value": 1234})
-        self.fakeParamToc.append({"varid": 2, "vartype": 0x06,
-                                  "vargroup": "rpid", "varname": "prp",
-                                  "writable": True, "value": 1.5})
-        self.fakeParamToc.append({"varid": 3, "vartype": 0x06,
-                                  "vargroup": "rpid", "varname": "pyaw",
-                                  "writable": True, "value": 2.5})
-        self.fakeParamToc.append({"varid": 4, "vartype": 0x06,
-                                  "vargroup": "rpid", "varname": "irp",
-                                  "writable": True, "value": 3.5})
-        self.fakeParamToc.append({"varid": 5, "vartype": 0x06,
-                                  "vargroup": "rpid", "varname": "iyaw",
-                                  "writable": True, "value": 4.5})
-        self.fakeParamToc.append({"varid": 6, "vartype": 0x06,
-                                  "vargroup": "pid_attitude",
-                                  "varname": "pitch_kd", "writable": True,
-                                  "value": 5.5})
-        self.fakeParamToc.append({"varid": 7, "vartype": 0x06,
-                                  "vargroup": "rpid", "varname": "dyaw",
-                                  "writable": True, "value": 6.5})
-        self.fakeParamToc.append({"varid": 8, "vartype": 0x06,
-                                  "vargroup": "apid", "varname": "prp",
-                                  "writable": True, "value": 7.5})
-        self.fakeParamToc.append({"varid": 9, "vartype": 0x06,
-                                  "vargroup": "apid", "varname": "pyaw",
-                                  "writable": True, "value": 8.5})
-        self.fakeParamToc.append({"varid": 10, "vartype": 0x06,
-                                  "vargroup": "apid", "varname": "irp",
-                                  "writable": True, "value": 9.5})
-        self.fakeParamToc.append({"varid": 11, "vartype": 0x06,
-                                  "vargroup": "apid", "varname": "iyaw",
-                                  "writable": True, "value": 10.5})
-        self.fakeParamToc.append({"varid": 12, "vartype": 0x06,
-                                  "vargroup": "apid", "varname": "drp",
-                                  "writable": True, "value": 11.5})
-        self.fakeParamToc.append({"varid": 13, "vartype": 0x06,
-                                  "vargroup": "apid", "varname": "dyaw",
-                                  "writable": True, "value": 12.5})
-        self.fakeParamToc.append({"varid": 14, "vartype": 0x08,
-                                  "vargroup": "flightctrl",
-                                  "varname": "xmode", "writable": True,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 15, "vartype": 0x08,
-                                  "vargroup": "flightctrl",
-                                  "varname": "ratepid", "writable": True,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 16, "vartype": 0x08,
-                                  "vargroup": "imu_sensors",
-                                  "varname": "HMC5883L", "writable": False,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 17, "vartype": 0x08,
-                                  "vargroup": "imu_sensors",
-                                  "varname": "MS5611", "writable": False,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 18, "vartype": 0x0A,
-                                  "vargroup": "firmware",
-                                  "varname": "revision0", "writable": False,
-                                  "value": 0xdeb})
-        self.fakeParamToc.append({"varid": 19, "vartype": 0x09,
-                                  "vargroup": "firmware",
-                                  "varname": "revision1", "writable": False,
-                                  "value": 0x99})
-        self.fakeParamToc.append({"varid": 20, "vartype": 0x08,
-                                  "vargroup": "firmware",
-                                  "varname": "modified", "writable": False,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 21, "vartype": 0x08,
-                                  "vargroup": "imu_tests",
-                                  "varname": "MPU6050", "writable": False,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 22, "vartype": 0x08,
-                                  "vargroup": "imu_tests",
-                                  "varname": "HMC5883L", "writable": False,
-                                  "value": 1})
-        self.fakeParamToc.append({"varid": 23, "vartype": 0x08,
-                                  "vargroup": "imu_tests",
-                                  "varname": "MS5611", "writable": False,
-                                  "value": 1})
-
-        self.fakeflash = {}
-        self._random_answer_delay = True
-        self.queue = queue.Queue()
-        self._packet_handler = _PacketHandlingThread(self.queue,
-                                                     self.fakeLogToc,
-                                                     self.fakeParamToc,
-                                                     self._fake_mems)
-        self._packet_handler.start()
-
-    def scan_interface(self, address):
-        return [["debug://0/0", "Normal connection"],
-                ["debug://0/1", "Fail to connect"],
-                ["debug://0/2", "Incomplete log TOC download"],
-                ["debug://0/3", "Insert random delays on replies"],
-                ["debug://0/4",
-                 "Insert random delays on replies and random TOC CRCs"],
-                ["debug://0/5", "Normal but random TOC CRCs"],
-                ["debug://0/6", "Normal but empty I2C and OW mems"]]
-
-    def get_status(self):
-        return "Ok"
-
-    def get_name(self):
-        return "debug"
-
-    def connect(self, uri, linkQualityCallback, linkErrorCallback):
-
-        if not re.search("^debug://", uri):
-            raise WrongUriType("Not a debug URI")
-
-        self._packet_handler.linkErrorCallback = linkErrorCallback
-        self._packet_handler.linkQualityCallback = linkQualityCallback
-
-        # Debug-options for this driver that
-        # is set by using different connection URIs
-        self._packet_handler.inhibitAnswers = False
-        self._packet_handler.doIncompleteLogTOC = False
-        self._packet_handler.bootloader = False
-        self._packet_handler._random_answer_delay = False
-        self._packet_handler._random_toc_crcs = False
-
-        if (re.search("^debug://.*/1\Z", uri)):
-            self._packet_handler.inhibitAnswers = True
-        if (re.search("^debug://.*/110\Z", uri)):
-            self._packet_handler.bootloader = True
-        if (re.search("^debug://.*/2\Z", uri)):
-            self._packet_handler.doIncompleteLogTOC = True
-        if (re.search("^debug://.*/3\Z", uri)):
-            self._packet_handler._random_answer_delay = True
-        if (re.search("^debug://.*/4\Z", uri)):
-            self._packet_handler._random_answer_delay = True
-            self._packet_handler._random_toc_crcs = True
-        if (re.search("^debug://.*/5\Z", uri)):
-            self._packet_handler._random_toc_crcs = True
-
-        if len(self._fake_mems) == 0:
-            # Add empty EEPROM
-            self._fake_mems.append(FakeMemory(type=0, size=100, addr=0))
-            # Add EEPROM with settings
-            self._fake_mems.append(
-                FakeMemory(type=0, size=100, addr=0,
-                           data=[48, 120, 66, 67, 1, 8, 0, 0, 0, 0,
-                                 0, 0, 0, 0, 0, 231, 8, 231, 231, 231, 218]))
-            # Add 1-wire memory with settings for LED-ring
-            self._fake_mems.append(
-                FakeMemory(type=1, size=112, addr=0x1234567890ABCDEF,
-                           data=[0xeb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-                                 0x44, 0x00, 0x0e,
-                                 0x01, 0x09, 0x62, 0x63, 0x4c, 0x65, 0x64,
-                                 0x52, 0x69, 0x6e,
-                                 0x67, 0x02, 0x01, 0x62, 0x55]))
-            # Add 1-wire memory with settings for LED-ring but bad CRC
-            self._fake_mems.append(
-                FakeMemory(type=1, size=112, addr=0x1234567890ABCDEF,
-                           data=[0xeb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-                                 0x44, 0x00, 0x0e,
-                                 0x01, 0x09, 0x62, 0x63, 0x4c, 0x65, 0x64,
-                                 0x52, 0x69, 0x6e,
-                                 0x67, 0x02, 0x01, 0x62, 0x56]))
-            # Add empty 1-wire memory
-            self._fake_mems.append(
-                FakeMemory(type=1, size=112, addr=0x1234567890ABCDEE,
-                           data=[0x00 for a in range(112)]))
-
-        if (re.search("^debug://.*/6\Z", uri)):
-            logger.info("------------->Erasing memories on connect")
-            for m in self._fake_mems:
-                m.erase()
-
-        self.fakeConsoleThread = None
-
-        if (not self._packet_handler.inhibitAnswers and
-                not self._packet_handler.bootloader):
-            self.fakeConsoleThread = FakeConsoleThread(self.queue)
-            self.fakeConsoleThread.start()
-
-        if (self._packet_handler.linkQualityCallback is not None):
-            self._packet_handler.linkQualityCallback(0)
-
-    def receive_packet(self, time=0):
-        if time == 0:
-            try:
-                return self.queue.get(False)
-            except queue.Empty:
-                return None
-        elif time < 0:
-            try:
-                return self.queue.get(True)
-            except queue.Empty:
-                return None
-        else:
-            try:
-                return self.queue.get(True, time)
-            except queue.Empty:
-                return None
-
-    def send_packet(self, pk):
-        self._packet_handler.handle_packet(pk)
-
-    def close(self):
-        logger.info("Closing debugdriver")
-        for f in self._packet_handler.fakeLoggingThreads:
-            f.stop()
-        if self.fakeConsoleThread:
-            self.fakeConsoleThread.stop()
-
-
-class _PacketHandlingThread(Thread):
-    """Thread for handling packets asynchronously"""
-
-    def __init__(self, out_queue, fake_log_toc, fake_param_toc, fake_mems):
-        Thread.__init__(self)
-        self.setDaemon(True)
-        self.queue = out_queue
-        self.fakeLogToc = fake_log_toc
-        self.fakeParamToc = fake_param_toc
-        self._fake_mems = fake_mems
-        self._in_queue = queue.Queue()
-
-        self.inhibitAnswers = False
-        self.doIncompleteLogTOC = False
-        self.bootloader = False
-        self._random_answer_delay = False
-        self._random_toc_crcs = False
-
-        self.linkErrorCallback = None
-        self.linkQualityCallback = None
-        random.seed(None)
-        self.fakeLoggingThreads = []
-
-        self._added_blocks = []
-
-        self.nowAnswerCounter = 4
-
-    def handle_packet(self, pk):
-        self._in_queue.put(pk)
-
-    def run(self):
-        while (True):
-            pk = self._in_queue.get(True)
-            if (self.inhibitAnswers):
-                self.nowAnswerCounter = self.nowAnswerCounter - 1
-                logger.debug(
-                    "Not answering with any data, will send link errori"
-                    " in %d retries", self.nowAnswerCounter)
-                if (self.nowAnswerCounter == 0):
-                    self.linkErrorCallback("Nothing is answering, and it"
-                                           " shouldn't")
-            else:
-                if (pk.port == 0xFF):
-                    self._handle_bootloader(pk)
-                elif (pk.port == CRTPPort.DEBUGDRIVER):
-                    self._handle_debugmessage(pk)
-                elif (pk.port == CRTPPort.COMMANDER):
-                    pass
-                elif (pk.port == CRTPPort.LOGGING):
-                    self._handle_logging(pk)
-                elif (pk.port == CRTPPort.PARAM):
-                    self.handleParam(pk)
-                elif (pk.port == CRTPPort.MEM):
-                    self._handle_mem_access(pk)
-                else:
-                    logger.warning(
-                        "Not handling incoming packets on port [%d]",
-                        pk.port)
-
-    def _handle_mem_access(self, pk):
-        chan = pk.channel
-        cmd = pk.data[0]
-        payload = pk.data[1:]
-
-        if chan == 0:  # Info channel
-            p_out = CRTPPacket()
-            p_out.set_header(CRTPPort.MEM, 0)
-            if cmd == 1:  # Request number of memories
-                p_out.data = (1, len(self._fake_mems))
-            if cmd == 2:
-                id = payload[0]
-                logger.info("Getting mem {}".format(id))
-                m = self._fake_mems[id]
-                p_out.data = struct.pack(
-                    '<BBBIQ', 2, id, m.type, m.size, m.addr)
-            self._send_packet(p_out)
-
-        if chan == 1:  # Read channel
-            id = cmd
-            addr = struct.unpack("I", payload[0:4])[0]
-            length = payload[4]
-            status = 0
-            logger.info("MEM: Read {}bytes at 0x{:X} from memory {}".format(
-                length, addr, id))
-            m = self._fake_mems[id]
-            p_out = CRTPPacket()
-            p_out.set_header(CRTPPort.MEM, 1)
-            p_out.data = struct.pack("<BIB", id, addr, status)
-            p_out.data += struct.pack("B" * length,
-                                      *m.data[addr:addr + length])
-            self._send_packet(p_out)
-
-        if chan == 2:  # Write channel
-            id = cmd
-            addr = struct.unpack("I", payload[0:4])[0]
-            data = payload[4:]
-            logger.info("MEM: Write {}bytes at 0x{:X} to memory {}".format(
-                len(data), addr, id))
-            m = self._fake_mems[id]
-
-            for i in range(len(data)):
-                m.data[addr + i] = data[i]
-
-            status = 0
-
-            p_out = CRTPPacket()
-            p_out.set_header(CRTPPort.MEM, 2)
-            p_out.data = struct.pack("<BIB", id, addr, status)
-            self._send_packet(p_out)
-
-    def _handle_bootloader(self, pk):
-        cmd = pk.data[1]
-        if (cmd == 0x10):  # Request info about copter
-            p = CRTPPacket()
-            p.set_header(0xFF, 0xFF)
-            pageSize = 1024
-            buffPages = 10
-            flashPages = 100
-            flashStart = 1
-            p.data = struct.pack('<BBHHHH', 0xFF, 0x10, pageSize, buffPages,
-                                 flashPages, flashStart)
-            p.data += struct.pack('B' * 12, 0xA0A1A2A3A4A5)
-            self._send_packet(p)
-            logging.info("Bootloader: Sending info back info")
-        elif (cmd == 0x14):  # Upload buffer
-            [page, addr] = struct.unpack('<HH', p.data[0:4])
-        elif (cmd == 0x18):  # Flash page
-            p = CRTPPacket()
-            p.set_header(0xFF, 0xFF)
-            p.data = struct.pack('<BBH', 0xFF, 0x18, 1)
-            self._send_packet(p)
-        elif (cmd == 0xFF):  # Reset to firmware
-            logger.info("Bootloader: Got reset command")
-        else:
-            logger.warning("Bootloader: Unknown command 0x%02X", cmd)
-
-    def _handle_debugmessage(self, pk):
-        if (pk.channel == 0):
-            cmd = struct.unpack("B", pk.data[0])[0]
-            if (cmd == 0):  # Fake link quality
-                newLinkQuality = struct.unpack("B", pk.data[1])[0]
-                self.linkQualityCallback(newLinkQuality)
-            elif (cmd == 1):
-                self.linkErrorCallback("DebugDriver was forced to disconnect!")
-            else:
-                logger.warning("Debug port: Not handling cmd=%d on channel 0",
-                               cmd)
-        else:
-            logger.warning("Debug port: Not handling channel=%d",
-                           pk.channel)
-
-    def _handle_toc_access(self, pk):
-        chan = pk.channel
-        cmd = pk.data[0]
-        logger.info("TOC access on port %d", pk.port)
-        if (chan == 0):  # TOC Access
-            cmd = pk.data[0]
-            if (cmd == 0):  # Reqest variable info
-                p = CRTPPacket()
-                p.set_header(pk.port, 0)
-                varIndex = 0
-                if (len(pk.data) > 1):
-                    varIndex = pk.data[1]
-                    logger.debug("TOC[%d]: Requesting ID=%d", pk.port,
-                                 varIndex)
-                else:
-                    logger.debug("TOC[%d]: Requesting first index..surprise,"
-                                 " it 0 !", pk.port)
-
-                if (pk.port == CRTPPort.LOGGING):
-                    l = self.fakeLogToc[varIndex]
-                if (pk.port == CRTPPort.PARAM):
-                    l = self.fakeParamToc[varIndex]
-
-                vartype = l["vartype"]
-                if (pk.port == CRTPPort.PARAM and l["writable"] is True):
-                    vartype = vartype | (0x10)
-
-                p.data = struct.pack("<BBB", cmd, l["varid"], vartype)
-                for ch in l["vargroup"]:
-                    p.data.append(ord(ch))
-                p.data.append(0)
-                for ch in l["varname"]:
-                    p.data.append(ord(ch))
-                p.data.append(0)
-                if (self.doIncompleteLogTOC is False):
-                    self._send_packet(p)
-                elif (varIndex < 5):
-                    self._send_packet(p)
-                else:
-                    logger.info("TOC: Doing incomplete TOC, stopping after"
-                                " varIndex => 5")
-
-            if (cmd == 1):  # TOC CRC32 request
-                fakecrc = 0
-                if (pk.port == CRTPPort.LOGGING):
-                    tocLen = len(self.fakeLogToc)
-                    fakecrc = 0xAAAAAAAA
-                if (pk.port == CRTPPort.PARAM):
-                    tocLen = len(self.fakeParamToc)
-                    fakecrc = 0xBBBBBBBB
-
-                if self._random_toc_crcs:
-                    fakecrc = int(''.join(
-                        random.choice("ABCDEF" + string.digits) for x in
-                        range(8)), 16)
-                    logger.debug("Generated random TOC CRC: 0x%x", fakecrc)
-                logger.info("TOC[%d]: Requesting TOC CRC, sending back fake"
-                            " stuff: %d", pk.port, len(self.fakeLogToc))
-                p = CRTPPacket()
-                p.set_header(pk.port, 0)
-                p.data = struct.pack('<BBIBB', 1, tocLen, fakecrc, 16, 24)
-                self._send_packet(p)
-
-    def handleParam(self, pk):
-        chan = pk.channel
-        cmd = pk.data[0]
-        logger.debug("PARAM: Port=%d, Chan=%d, cmd=%d", pk.port,
-                     chan, cmd)
-        if (chan == 0):  # TOC Access
-            self._handle_toc_access(pk)
-        elif (chan == 2):  # Settings access
-            varId = pk.data[0]
-            formatStr = ParamTocElement.types[
-                self.fakeParamToc[varId]["vartype"]][1]
-            newvalue = struct.unpack(formatStr, pk.data[1:])[0]
-            self.fakeParamToc[varId]["value"] = newvalue
-            logger.info("PARAM: New value [%s] for param [%d]", newvalue,
-                        varId)
-            # Send back the new value
-            p = CRTPPacket()
-            p.set_header(pk.port, 2)
-            p.data += struct.pack("<B", varId)
-            p.data += struct.pack(formatStr, self.fakeParamToc[varId]["value"])
-            self._send_packet(p)
-        elif (chan == 1):
-            p = CRTPPacket()
-            p.set_header(pk.port, 1)
-            varId = cmd
-            p.data.append(varId)
-            formatStr = ParamTocElement.types[
-                self.fakeParamToc[varId]["vartype"]][1]
-            p.data += struct.pack(formatStr, self.fakeParamToc[varId]["value"])
-            logger.info("PARAM: Getting value for %d", varId)
-            self._send_packet(p)
-
-    def _handle_logging(self, pk):
-        chan = pk.channel
-        cmd = pk.data[0]
-        logger.debug("LOG: Chan=%d, cmd=%d", chan, cmd)
-        if (chan == 0):  # TOC Access
-            self._handle_toc_access(pk)
-        elif (chan == 1):  # Settings access
-            if (cmd == 0):
-                blockId = pk.data[1]
-                if blockId not in self._added_blocks:
-                    self._added_blocks.append(blockId)
-                    logger.info("LOG:Adding block id=%d", blockId)
-                    listofvars = pk.data[3:]
-                    fakeThread = _FakeLoggingDataThread(self.queue, blockId,
-                                                        listofvars,
-                                                        self.fakeLogToc)
-                    self.fakeLoggingThreads.append(fakeThread)
-                    fakeThread.start()
-                    # Anser that everything is ok
-                    p = CRTPPacket()
-                    p.set_header(5, 1)
-                    p.data = struct.pack('<BBB', 0, blockId, 0x00)
-                    self._send_packet(p)
-                else:
-                    p = CRTPPacket()
-                    p.set_header(5, 1)
-                    p.data = struct.pack('<BBB', 0, blockId, errno.EEXIST)
-                    self._send_packet(p)
-            if (cmd == 1):
-                logger.warning("LOG: Appending block not implemented!")
-            if (cmd == 2):
-                blockId = pk.data[1]
-                logger.info("LOG: Should delete block %d", blockId)
-                success = False
-                for fb in self.fakeLoggingThreads:
-                    if (fb.blockId == blockId):
-                        fb._disable_logging()
-                        fb.stop()
-
-                        p = CRTPPacket()
-                        p.set_header(5, 1)
-                        p.data = struct.pack('<BBB', cmd, blockId, 0x00)
-                        self._send_packet(p)
-                        logger.info("LOG: Deleted block=%d", blockId)
-                        success = True
-                if (success is False):
-                    logger.warning("LOG: Could not delete block=%d, not found",
-                                   blockId)
-                    # TODO: Send back error code
-
-            if (cmd == 3):
-                blockId = pk.data[1]
-                period = pk.data[2] * 10  # Sent as multiple of 10 ms
-                logger.info("LOG:Starting block %d", blockId)
-                success = False
-                for fb in self.fakeLoggingThreads:
-                    if (fb.blockId == blockId):
-                        fb._enable_logging()
-                        fb.period = period
-                        p = CRTPPacket()
-                        p.set_header(5, 1)
-                        p.data = struct.pack('<BBB', cmd, blockId, 0x00)
-                        self._send_packet(p)
-                        logger.info("LOG:Started block=%d", blockId)
-                        success = True
-                if (success is False):
-                    logger.info("LOG:Could not start block=%d, not found",
-                                blockId)
-                    # TODO: Send back error code
-            if (cmd == 4):
-                blockId = pk.data[1]
-                logger.info("LOG:Pausing block %d", blockId)
-                success = False
-                for fb in self.fakeLoggingThreads:
-                    if (fb.blockId == blockId):
-                        fb._disable_logging()
-                        p = CRTPPacket()
-                        p.set_header(5, 1)
-                        p.data = struct.pack('<BBB', cmd, blockId, 0x00)
-                        self._send_packet(p)
-                        logger.info("LOG:Pause block=%d", blockId)
-                        success = True
-                if (success is False):
-                    logger.warning("LOG:Could not pause block=%d, not found",
-                                   blockId)
-                    # TODO: Send back error code
-            if (cmd == 5):
-                logger.info("LOG: Reset logging, but doing nothing")
-                p = CRTPPacket()
-                p.set_header(5, 1)
-                p.data = struct.pack('<BBB', cmd, 0x00, 0x00)
-                self._send_packet(p)
-
-        elif (chan > 1):
-            logger.warning("LOG: Uplink packets with channels > 1 not"
-                           " supported!")
-
-    def _send_packet(self, pk):
-        # Do not delay log data
-        if (self._random_answer_delay and pk.port != 0x05 and
-                pk.channel != 0x02):
-            # Calculate a delay between 0ms and 250ms
-            delay = random.randint(0, 250) / 1000.0
-            logger.debug("Delaying answer %.2fms", delay * 1000)
-            time.sleep(delay)
-        self.queue.put(pk)
-
-
-class _FakeLoggingDataThread(Thread):
-    """Thread that will send back fake logging data via CRTP"""
-
-    def __init__(self, outQueue, blockId, listofvars, fakeLogToc):
-        Thread.__init__(self)
-        self.starttime = datetime.now()
-        self.outQueue = outQueue
-        self.setDaemon(True)
-        self.mod = 0
-        self.blockId = blockId
-        self.period = 0
-        self.listofvars = listofvars
-        self.shouldLog = False
-        self.fakeLogToc = fakeLogToc
-        self.fakeLoggingData = []
-        self.setName("Fakelog block=%d" % blockId)
-        self.shouldQuit = False
-
-        logging.info("FakeDataLoggingThread created for blockid=%d", blockId)
-        i = 0
-        while (i < len(listofvars)):
-            varType = listofvars[i]
-            var_stored_as = (varType >> 8)
-            var_fetch_as = (varType & 0xFF)
-            if (var_stored_as > 0):
-                addr = struct.unpack("<I", listofvars[i + 1:i + 5])
-                logger.debug("FakeLoggingThread: We should log a memory addr"
-                             " 0x%04X", addr)
-                self.fakeLoggingData.append([memlogging[var_fetch_as],
-                                             memlogging[var_fetch_as]["min"],
-                                             1])
-                i = i + 5
-            else:
-                varId = listofvars[i]
-                logger.debug("FakeLoggingThread: We should log variable from"
-                             " TOC: id=%d, type=0x%02X", varId, varType)
-                for t in self.fakeLogToc:
-                    if (varId == t["varid"]):
-                        # Each touple will have var data and current fake value
-                        self.fakeLoggingData.append([t, t["min"], 1])
-                i = i + 2
-
-    def _enable_logging(self):
-        self.shouldLog = True
-        logging.info("_FakeLoggingDataThread: Enable thread [%s] at period %d",
-                     self.getName(), self.period)
-
-    def _disable_logging(self):
-        self.shouldLog = False
-        logging.info("_FakeLoggingDataThread: Disable thread [%s]",
-                     self.getName())
-
-    def stop(self):
-        self.shouldQuit = True
-
-    def run(self):
-        while (self.shouldQuit is False):
-            if (self.shouldLog is True):
-
-                p = CRTPPacket()
-                p.set_header(5, 2)
-                p.data = struct.pack('<B', self.blockId)
-                timestamp = int(
-                    (datetime.now() - self.starttime).total_seconds() * 1000)
-                p.data += struct.pack('BBB', timestamp & 0xff,
-                                      (timestamp >> 8) & 0x0ff,
-                                      (timestamp >> 16) & 0x0ff)  # Timestamp
-
-                for d in self.fakeLoggingData:
-                    # Set new value
-                    d[1] = d[1] + d[0]["mod"] * d[2]
-                    # Obej the limitations
-                    if (d[1] > d[0]["max"]):
-                        d[1] = d[0]["max"]  # Limit value
-                        d[2] = -1  # Switch direction
-                    if (d[1] < d[0]["min"]):
-                        d[1] = d[0]["min"]  # Limit value
-                        d[2] = 1  # Switch direction
-                    # Pack value
-                    formatStr = LogTocElement.types[d[0]["vartype"]][1]
-                    p.data += struct.pack(formatStr, d[1])
-                self.outQueue.put(p)
-            time.sleep(self.period / 1000.0)  # Period in ms here
-
-
-class FakeConsoleThread(Thread):
-    """Thread that will send back fake console data via CRTP"""
-
-    def __init__(self, outQueue):
-        Thread.__init__(self)
-        self.outQueue = outQueue
-        self.setDaemon(True)
-        self._should_run = True
-
-    def stop(self):
-        self._shoud_run = False
-
-    def run(self):
-        # Temporary hack to test GPS from firmware by sending NMEA string
-        # on console
-        long_val = 0
-        lat_val = 0
-        alt_val = 0
-
-        while (self._should_run):
-            long_val += 1
-            lat_val += 1
-            alt_val += 1.0
-
-            long_string = "5536.677%d" % (long_val % 99)
-            lat_string = "01259.645%d" % (lat_val % 99)
-            alt_string = "%.1f" % (alt_val % 100.0)
-
-            # Copy of what is sent from the module, but note that only
-            # the GPGGA message is being simulated, the others are fixed...
-            self._send_text("Time is now %s\n" % datetime.now())
-            self._send_text("$GPVTG,,T,,M,0.386,N,0.716,K,A*2E\n")
-            self._send_text("$GPGGA,135544.0")
-            self._send_text("0,%s,N,%s,E,1,04,2.62,3.6,M,%s,M,,*58\n" % (
-                long_string, lat_string, alt_string))
-            self._send_text(
-                "$GPGSA,A,3,31,20,23,07,,,,,,,,,3.02,2.62,1.52*05\n")
-            self._send_text("$GPGSV,2,1,07,07,09,181,15,13,63,219,26,16,02,"
-                            "097,,17,05,233,20*7E\n")
-            self._send_text(
-                "$GPGSV,2,2,07,20,42,119,35,23,77,097,27,31,12,032,19*47\n")
-            self._send_text(
-                "$GPGLL,5536.67734,N,01259.64578,E,135544.00,A,A*68\n")
-
-            time.sleep(2)
-
-    def _send_text(self, message):
-        p = CRTPPacket()
-        p.set_header(0, 0)
-
-        us = "%is" % len(message)
-        # This might be done prettier ;-)
-        p.data = message
-
-        self.outQueue.put(p)
diff --git a/src/cflib/cflib/crtp/exceptions.py b/src/cflib/cflib/crtp/exceptions.py
deleted file mode 100644
index 876f9ee000e4e96560291cd0956899c7611ef9f5..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/exceptions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Exception used when the URI is not for the current driver
-(ie. radio:// for the serial driver ...)
-It basically means that an other driver could do the job
-It does NOT means that the URI is good or bad
-"""
-
-__author__ = 'Bitcraze AB'
-__all__ = ['WrongUriType', 'CommunicationException']
-
-
-class WrongUriType(Exception):
-    """ Wrong type of URI for this interface """
-    pass
-
-
-class CommunicationException(Exception):
-    """ Communication problem when communicating with a Crazyflie """
-    pass
diff --git a/src/cflib/cflib/crtp/radiodriver.py b/src/cflib/cflib/crtp/radiodriver.py
deleted file mode 100644
index 01a7b8fa72e2618179602f2880002e06a6137970..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/radiodriver.py
+++ /dev/null
@@ -1,484 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Crazyradio CRTP link driver.
-
-This driver is used to communicate with the Crazyflie using the Crazyradio
-USB dongle.
-"""
-
-import collections
-import logging
-import sys
-from cflib.crtp.crtpdriver import CRTPDriver
-from .crtpstack import CRTPPacket
-from .exceptions import WrongUriType
-import threading
-import re
-import array
-import binascii
-import struct
-
-from cflib.drivers.crazyradio import Crazyradio
-from usb import USBError
-
-if sys.version_info < (3,):
-    import Queue as queue
-else:
-    import queue
-
-
-__author__ = 'Bitcraze AB'
-__all__ = ['RadioDriver']
-
-logger = logging.getLogger(__name__)
-
-
-class RadioDriver(CRTPDriver):
-    """ Crazyradio link driver """
-
-    def __init__(self):
-        """ Create the link driver """
-        CRTPDriver.__init__(self)
-        self.cradio = None
-        self.uri = ""
-        self.link_error_callback = None
-        self.link_quality_callback = None
-        self.in_queue = None
-        self.out_queue = None
-        self._thread = None
-        self.needs_resending = True
-
-    def connect(self, uri, link_quality_callback, link_error_callback):
-        """
-        Connect the link driver to a specified URI of the format:
-        radio://<dongle nbr>/<radio channel>/[250K,1M,2M]
-
-        The callback for linkQuality can be called at any moment from the
-        driver to report back the link quality in percentage. The
-        callback from linkError will be called when a error occurs with
-        an error message.
-        """
-
-        # check if the URI is a radio URI
-        if not re.search("^radio://", uri):
-            raise WrongUriType("Not a radio URI")
-
-        # Open the USB dongle
-        if not re.search("^radio://([0-9]+)((/([0-9]+))"
-                         "((/(250K|1M|2M))?(/([A-F0-9]+))?)?)?$", uri):
-            raise WrongUriType('Wrong radio URI format!')
-
-        uri_data = re.search("^radio://([0-9]+)((/([0-9]+))"
-                             "((/(250K|1M|2M))?(/([A-F0-9]+))?)?)?$", uri)
-
-        self.uri = uri
-
-        channel = 2
-        if uri_data.group(4):
-            channel = int(uri_data.group(4))
-
-        datarate = Crazyradio.DR_2MPS
-        if uri_data.group(7) == "250K":
-            datarate = Crazyradio.DR_250KPS
-        if uri_data.group(7) == "1M":
-            datarate = Crazyradio.DR_1MPS
-        if uri_data.group(7) == "2M":
-            datarate = Crazyradio.DR_2MPS
-
-        if self.cradio is None:
-            self.cradio = Crazyradio(devid=int(uri_data.group(1)))
-        else:
-            raise Exception("Link already open!")
-
-        if self.cradio.version >= 0.4:
-            self.cradio.set_arc(10)
-        else:
-            logger.warning("Radio version <0.4 will be obsoleted soon!")
-
-        self.cradio.set_channel(channel)
-
-        self.cradio.set_data_rate(datarate)
-
-        if uri_data.group(9):
-            addr = str(uri_data.group(9))
-            new_addr = struct.unpack("<BBBBB", binascii.unhexlify(addr))
-            self.cradio.set_address(new_addr)
-
-        # Prepare the inter-thread communication queue
-        self.in_queue = queue.Queue()
-        # Limited size out queue to avoid "ReadBack" effect
-        self.out_queue = queue.Queue(1)
-
-        # Launch the comm thread
-        self._thread = _RadioDriverThread(self.cradio, self.in_queue,
-                                          self.out_queue,
-                                          link_quality_callback,
-                                          link_error_callback,
-                                          self)
-        self._thread.start()
-
-        self.link_error_callback = link_error_callback
-
-    def receive_packet(self, time=0):
-        """
-        Receive a packet though the link. This call is blocking but will
-        timeout and return None if a timeout is supplied.
-        """
-        if time == 0:
-            try:
-                return self.in_queue.get(False)
-            except queue.Empty:
-                return None
-        elif time < 0:
-            try:
-                return self.in_queue.get(True)
-            except queue.Empty:
-                return None
-        else:
-            try:
-                return self.in_queue.get(True, time)
-            except queue.Empty:
-                return None
-
-    def send_packet(self, pk):
-        """ Send the packet pk though the link """
-        # if self.out_queue.full():
-        #    self.out_queue.get()
-        if (self.cradio is None):
-            return
-
-        try:
-            self.out_queue.put(pk, True, 2)
-        except queue.Full:
-            if self.link_error_callback:
-                self.link_error_callback("RadioDriver: Could not send packet"
-                                         " to copter")
-
-    def pause(self):
-        self._thread.stop()
-        self._thread = None
-
-    def restart(self):
-        if self._thread:
-            return
-
-        self._thread = _RadioDriverThread(self.cradio, self.in_queue,
-                                          self.out_queue,
-                                          self.link_quality_callback,
-                                          self.link_error_callback,
-                                          self)
-        self._thread.start()
-
-    def close(self):
-        """ Close the link. """
-        # Stop the comm thread
-        self._thread.stop()
-
-        # Close the USB dongle
-        try:
-            if self.cradio:
-                self.cradio.close()
-        except:
-            # If we pull out the dongle we will not make this call
-            pass
-        self.cradio = None
-
-        while not self.out_queue.empty():
-            self.out_queue.get()
-
-        # Clear callbacks
-        self.link_error_callback = None
-        self.link_quality_callback = None
-
-    def _scan_radio_channels(self, start=0, stop=125):
-        """ Scan for Crazyflies between the supplied channels. """
-        return list(self.cradio.scan_channels(start, stop, (0xff,)))
-
-    def scan_selected(self, links):
-        to_scan = ()
-        for l in links:
-            one_to_scan = {}
-            uri_data = re.search("^radio://([0-9]+)((/([0-9]+))"
-                                 "(/(250K|1M|2M))?)?$",
-                                 l)
-
-            one_to_scan["channel"] = int(uri_data.group(4))
-
-            datarate = Crazyradio.DR_2MPS
-            if uri_data.group(6) == "250K":
-                datarate = Crazyradio.DR_250KPS
-            if uri_data.group(6) == "1M":
-                datarate = Crazyradio.DR_1MPS
-            if uri_data.group(6) == "2M":
-                datarate = Crazyradio.DR_2MPS
-
-            one_to_scan["datarate"] = datarate
-
-            to_scan += (one_to_scan,)
-
-        found = self.cradio.scan_selected(to_scan, (0xFF, 0xFF, 0xFF))
-
-        ret = ()
-        for f in found:
-            dr_string = ""
-            if f["datarate"] == Crazyradio.DR_2MPS:
-                dr_string = "2M"
-            if f["datarate"] == Crazyradio.DR_250KPS:
-                dr_string = "250K"
-            if f["datarate"] == Crazyradio.DR_1MPS:
-                dr_string = "1M"
-
-            ret += ("radio://0/{}/{}".format(f["channel"], dr_string),)
-
-        return ret
-
-    def scan_interface(self, address):
-        """ Scan interface for Crazyflies """
-        if self.cradio is None:
-            try:
-                self.cradio = Crazyradio()
-            except Exception:
-                return []
-        else:
-            raise Exception("Cannot scann for links while the link is open!")
-
-        # FIXME: implements serial number in the Crazyradio driver!
-        serial = "N/A"
-
-        logger.info("v%s dongle with serial %s found", self.cradio.version,
-                    serial)
-        found = []
-
-        if address is not None:
-            addr = "{:X}".format(address)
-            new_addr = struct.unpack("<BBBBB", binascii.unhexlify(addr))
-            self.cradio.set_address(new_addr)
-
-        self.cradio.set_arc(1)
-
-        self.cradio.set_data_rate(self.cradio.DR_250KPS)
-
-        if address is None or address == 0xE7E7E7E7E7:
-            found += [["radio://0/{}/250K".format(c), ""]
-                      for c in self._scan_radio_channels()]
-            self.cradio.set_data_rate(self.cradio.DR_1MPS)
-            found += [["radio://0/{}/1M".format(c), ""]
-                      for c in self._scan_radio_channels()]
-            self.cradio.set_data_rate(self.cradio.DR_2MPS)
-            found += [["radio://0/{}/2M".format(c), ""]
-                      for c in self._scan_radio_channels()]
-        else:
-            found += [["radio://0/{}/250K/{:X}".format(c, address), ""]
-                      for c in self._scan_radio_channels()]
-            self.cradio.set_data_rate(self.cradio.DR_1MPS)
-            found += [["radio://0/{}/1M/{:X}".format(c, address), ""]
-                      for c in self._scan_radio_channels()]
-            self.cradio.set_data_rate(self.cradio.DR_2MPS)
-            found += [["radio://0/{}/2M/{:X}".format(c, address), ""]
-                      for c in self._scan_radio_channels()]
-
-        self.cradio.close()
-        self.cradio = None
-
-        return found
-
-    def get_status(self):
-        if self.cradio is None:
-            try:
-                self.cradio = Crazyradio()
-            except USBError as e:
-                return "Cannot open Crazyradio. Permission problem?" \
-                       " ({})".format(str(e))
-            except Exception as e:
-                return str(e)
-
-        ver = self.cradio.version
-        self.cradio.close()
-        self.cradio = None
-
-        return "Crazyradio version {}".format(ver)
-
-    def get_name(self):
-        return "radio"
-
-
-# Transmit/receive radio thread
-class _RadioDriverThread(threading.Thread):
-    """
-    Radio link receiver thread used to read data from the
-    Crazyradio USB driver. """
-
-    RETRYCOUNT_BEFORE_DISCONNECT = 10
-
-    def __init__(self, cradio, inQueue, outQueue, link_quality_callback,
-                 link_error_callback, link):
-        """ Create the object """
-        threading.Thread.__init__(self)
-        self.cradio = cradio
-        self.in_queue = inQueue
-        self.out_queue = outQueue
-        self.sp = False
-        self.link_error_callback = link_error_callback
-        self.link_quality_callback = link_quality_callback
-        self.retryBeforeDisconnect = self.RETRYCOUNT_BEFORE_DISCONNECT
-        self.retries = collections.deque()
-        self.retry_sum = 0
-
-        self.curr_up = 0
-        self.curr_down = 1
-
-        self.has_safelink = False
-        self._link = link
-
-    def stop(self):
-        """ Stop the thread """
-        self.sp = True
-        try:
-            self.join()
-        except Exception:
-            pass
-
-    def _send_packet_safe(self, cr, packet):
-        """
-        Adds 1bit counter to CRTP header to guarantee that no ack (downlink)
-        payload are lost and no uplink packet are duplicated.
-        The caller should resend packet if not acked (ie. same as with a
-        direct call to crazyradio.send_packet)
-        """
-        packet = bytearray(packet)
-        packet[0] &= 0xF3
-        packet[0] |= self.curr_up << 3 | self.curr_down << 2
-        resp = cr.send_packet(packet)
-        if resp and resp.ack and len(resp.data) and \
-           (resp.data[0] & 0x04) == (self.curr_down << 2):
-            self.curr_down = 1 - self.curr_down
-        if resp and resp.ack:
-            self.curr_up = 1 - self.curr_up
-
-        return resp
-
-    def run(self):
-        """ Run the receiver thread """
-        dataOut = array.array('B', [0xFF])
-        waitTime = 0
-        emptyCtr = 0
-
-        # Try up to 10 times to enable the safelink mode
-        for _ in range(10):
-            resp = self.cradio.send_packet((0xff, 0x05, 0x01))
-            if resp and resp.data and tuple(resp.data) == (0xff, 0x05, 0x01):
-                self.has_safelink = True
-                self.curr_up = 0
-                self.curr_down = 0
-                break
-        logging.info("Has safelink: {}".format(self.has_safelink))
-        self._link.needs_resending = not self.has_safelink
-
-        while (True):
-            if (self.sp):
-                break
-
-            try:
-                if self.has_safelink:
-                    ackStatus = self._send_packet_safe(self.cradio, dataOut)
-                else:
-                    ackStatus = self.cradio.send_packet(dataOut)
-            except Exception as e:
-                import traceback
-
-                self.link_error_callback(
-                    "Error communicating with crazy radio ,it has probably "
-                    "been unplugged!\nException:%s\n\n%s" % (
-                        e, traceback.format_exc()))
-
-            # Analise the in data packet ...
-            if ackStatus is None:
-                if (self.link_error_callback is not None):
-                    self.link_error_callback("Dongle communication error"
-                                             " (ackStatus==None)")
-                continue
-
-            if (self.link_quality_callback is not None):
-                # track the mean of a sliding window of the last N packets
-                retry = 10 - ackStatus.retry
-                self.retries.append(retry)
-                self.retry_sum += retry
-                if len(self.retries) > 100:
-                    self.retry_sum -= self.retries.popleft()
-                link_quality = float(self.retry_sum) / len(self.retries) * 10
-                self.link_quality_callback(link_quality)
-
-            # If no copter, retry
-            if ackStatus.ack is False:
-                self.retryBeforeDisconnect = self.retryBeforeDisconnect - 1
-                if (self.retryBeforeDisconnect == 0 and
-                        self.link_error_callback is not None):
-                    self.link_error_callback("Too many packets lost")
-                continue
-            self.retryBeforeDisconnect = self.RETRYCOUNT_BEFORE_DISCONNECT
-
-            data = ackStatus.data
-
-            # If there is a copter in range, the packet is analysed and the
-            # next packet to send is prepared
-            if (len(data) > 0):
-                inPacket = CRTPPacket(data[0], list(data[1:]))
-                # print "<- " + inPacket.__str__()
-                self.in_queue.put(inPacket)
-                waitTime = 0
-                emptyCtr = 0
-            else:
-                emptyCtr += 1
-                if (emptyCtr > 10):
-                    emptyCtr = 10
-                    # Relaxation time if the last 10 packet where empty
-                    waitTime = 0.01
-                else:
-                    waitTime = 0
-
-            # get the next packet to send of relaxation (wait 10ms)
-            outPacket = None
-            try:
-                outPacket = self.out_queue.get(True, waitTime)
-            except queue.Empty:
-                outPacket = None
-
-            dataOut = array.array('B')
-
-            if outPacket:
-                # print "-> " + outPacket.__str__()
-                dataOut.append(outPacket.header)
-                for X in outPacket.data:
-                    if type(X) == int:
-                        dataOut.append(X)
-                    else:
-                        dataOut.append(ord(X))
-            else:
-                dataOut.append(0xFF)
diff --git a/src/cflib/cflib/crtp/serialdriver.py b/src/cflib/cflib/crtp/serialdriver.py
deleted file mode 100644
index b307f3a047a8d62fd8b8787803c0b0b61700f270..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/serialdriver.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-An early serial link driver. This could still be used (after some fixing) to
-run high-speed CRTP with the Crazyflie. The UART can be run at 2Mbit.
-"""
-
-from .crtpdriver import CRTPDriver
-
-from .exceptions import WrongUriType
-
-import re
-
-__author__ = 'Bitcraze AB'
-__all__ = ['SerialDriver']
-
-
-class SerialDriver(CRTPDriver):
-    def __init__(self):
-        None
-
-    def connect(self, uri, linkQualityCallback, linkErrorCallback):
-        # check if the URI is a serial URI
-        if not re.search("^serial://", uri):
-            raise WrongUriType("Not a serial URI")
-
-        # Check if it is a valid serial URI
-        uriRe = re.search("^serial://([a-z A-Z 0-9]+)/?([0-9]+)?$", uri)
-        if not uriRe:
-            raise Exception("Invalid serial URI")
-
-    def get_name(self):
-        return "serial"
-
-    def scan_interface(self, address):
-        return []
diff --git a/src/cflib/cflib/crtp/udpdriver.py b/src/cflib/cflib/crtp/udpdriver.py
deleted file mode 100644
index d93d401d2c30855ebaa63c1b025e5b19c288a205..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/udpdriver.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-""" CRTP UDP Driver. Work either with the UDP server or with an UDP device
-See udpserver.py for the protocol"""
-
-from .crtpdriver import CRTPDriver
-from .crtpstack import CRTPPacket
-from .exceptions import WrongUriType
-import sys
-import re
-import struct
-from socket import socket
-if sys.version_info < (3,):
-    import Queue as queue
-else:
-    import queue
-
-__author__ = 'Bitcraze AB'
-__all__ = ['UdpDriver']
-
-
-class UdpDriver(CRTPDriver):
-    def __init__(self):
-        None
-
-    def connect(self, uri, linkQualityCallback, linkErrorCallback):
-        # check if the URI is a radio URI
-        if not re.search("^udp://", uri):
-            raise WrongUriType("Not an UDP URI")
-
-        self.queue = queue.Queue()
-        self.socket = socket(socket.AF_INET, socket.SOCK_DGRAM)
-        self.addr = ("localhost", 7777)
-        self.socket.connect(self.addr)
-
-        # Add this to the server clients list
-        self.socket.sendto("\xFF\x01\x01\x01", self.addr)
-
-    def receive_packet(self, time=0):
-        data, addr = self.socket.recvfrom(1024)
-
-        if data:
-            data = struct.unpack('b' * (len(data) - 1), data[0:len(data) - 1])
-            pk = CRTPPacket()
-            pk.port = data[0]
-            pk.data = data[1:]
-            return pk
-
-        try:
-            if time == 0:
-                return self.rxqueue.get(False)
-            elif time < 0:
-                while True:
-                    return self.rxqueue.get(True, 10)
-            else:
-                return self.rxqueue.get(True, time)
-        except queue.Empty:
-            return None
-
-    def send_packet(self, pk):
-        raw = (pk.port,) + struct.unpack("B" * len(pk.data), pk.data)
-
-        cksum = 0
-        for i in raw:
-            cksum += i
-
-        cksum %= 256
-
-        data = ''.join(chr(v) for v in (raw + (cksum,)))
-
-        # print tuple(data)
-        self.socket.sendto(data, self.addr)
-
-    def close(self):
-        # Remove this from the server clients list
-        self.socket.sendto("\xFF\x01\x02\x02", self.addr)
-
-    def get_name(self):
-        return "udp"
-
-    def scan_interface(self, address):
-        return []
diff --git a/src/cflib/cflib/crtp/usbdriver.py b/src/cflib/cflib/crtp/usbdriver.py
deleted file mode 100644
index 083d9fad8e5f97c42c6ab1971f353cbdd4b0292c..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/crtp/usbdriver.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Crazyflie USB driver.
-
-This driver is used to communicate with the Crazyflie using the USB connection.
-"""
-
-import logging
-
-from cflib.crtp.crtpdriver import CRTPDriver
-from .crtpstack import CRTPPacket
-from .exceptions import WrongUriType
-import threading
-import sys
-import re
-import time
-
-from cflib.drivers.cfusb import CfUsb
-from usb import USBError
-if sys.version_info < (3,):
-    import Queue as queue
-else:
-    import queue
-
-__author__ = 'Bitcraze AB'
-__all__ = ['UsbDriver']
-
-logger = logging.getLogger(__name__)
-
-
-class UsbDriver(CRTPDriver):
-    """ Crazyradio link driver """
-
-    def __init__(self):
-        """ Create the link driver """
-        CRTPDriver.__init__(self)
-        self.cfusb = None
-        self.uri = ""
-        self.link_error_callback = None
-        self.link_quality_callback = None
-        self.in_queue = None
-        self.out_queue = None
-        self._thread = None
-        self.needs_resending = False
-
-    def connect(self, uri, link_quality_callback, link_error_callback):
-        """
-        Connect the link driver to a specified URI of the format:
-        radio://<dongle nbr>/<radio channel>/[250K,1M,2M]
-
-        The callback for linkQuality can be called at any moment from the
-        driver to report back the link quality in percentage. The
-        callback from linkError will be called when a error occues with
-        an error message.
-        """
-
-        # check if the URI is a radio URI
-        if not re.search("^usb://", uri):
-            raise WrongUriType("Not a radio URI")
-
-        # Open the USB dongle
-        if not re.search("^usb://([0-9]+)$",
-                         uri):
-            raise WrongUriType('Wrong radio URI format!')
-
-        uri_data = re.search("^usb://([0-9]+)$",
-                             uri)
-
-        self.uri = uri
-
-        if self.cfusb is None:
-            self.cfusb = CfUsb(devid=int(uri_data.group(1)))
-            if self.cfusb.dev:
-                self.cfusb.set_crtp_to_usb(True)
-            else:
-                self.cfusb = None
-                raise Exception("Could not open {}".format(self.uri))
-
-        else:
-            raise Exception("Link already open!")
-
-        # Prepare the inter-thread communication queue
-        self.in_queue = queue.Queue()
-        # Limited size out queue to avoid "ReadBack" effect
-        self.out_queue = queue.Queue(50)
-
-        # Launch the comm thread
-        self._thread = _UsbReceiveThread(self.cfusb, self.in_queue,
-                                         link_quality_callback,
-                                         link_error_callback)
-        self._thread.start()
-
-        self.link_error_callback = link_error_callback
-
-    def receive_packet(self, time=0):
-        """
-        Receive a packet though the link. This call is blocking but will
-        timeout and return None if a timeout is supplied.
-        """
-        if time == 0:
-            try:
-                return self.in_queue.get(False)
-            except queue.Empty:
-                return None
-        elif time < 0:
-            try:
-                return self.in_queue.get(True)
-            except queue.Empty:
-                return None
-        else:
-            try:
-                return self.in_queue.get(True, time)
-            except queue.Empty:
-                return None
-
-    def send_packet(self, pk):
-        """ Send the packet pk though the link """
-        # if self.out_queue.full():
-        #    self.out_queue.get()
-        if (self.cfusb is None):
-            return
-
-        try:
-            dataOut = (pk.header,)
-            dataOut += pk.datat
-            self.cfusb.send_packet(dataOut)
-        except queue.Full:
-            if self.link_error_callback:
-                self.link_error_callback(
-                    "UsbDriver: Could not send packet to Crazyflie")
-
-    def pause(self):
-        self._thread.stop()
-        self._thread = None
-
-    def restart(self):
-        if self._thread:
-            return
-
-        self._thread = _UsbReceiveThread(self.cfusb, self.in_queue,
-                                         self.link_quality_callback,
-                                         self.link_error_callback)
-        self._thread.start()
-
-    def close(self):
-        """ Close the link. """
-        # Stop the comm thread
-        self._thread.stop()
-
-        # Close the USB dongle
-        try:
-            if self.cfusb:
-                self.cfusb.set_crtp_to_usb(False)
-                self.cfusb.close()
-        except Exception as e:
-            # If we pull out the dongle we will not make this call
-            logger.info("Could not close {}".format(e))
-            pass
-        self.cfusb = None
-
-    def scan_interface(self, address):
-        """ Scan interface for Crazyflies """
-        if self.cfusb is None:
-            try:
-                self.cfusb = CfUsb()
-            except Exception as e:
-                logger.warn(
-                    "Exception while scanning for Crazyflie USB: {}".format(
-                        str(e)))
-                return []
-        else:
-            raise Exception("Cannot scan for links while the link is open!")
-
-        # FIXME: implements serial number in the Crazyradio driver!
-        # serial = "N/A"
-
-        found = self.cfusb.scan()
-
-        self.cfusb.close()
-        self.cfusb = None
-
-        return found
-
-    def get_status(self):
-        return "No information available"
-
-    def get_name(self):
-        return "UsbCdc"
-
-
-# Transmit/receive radio thread
-class _UsbReceiveThread(threading.Thread):
-    """
-    Radio link receiver thread used to read data from the
-    Crazyradio USB driver. """
-
-    # RETRYCOUNT_BEFORE_DISCONNECT = 10
-
-    def __init__(self, cfusb, inQueue, link_quality_callback,
-                 link_error_callback):
-        """ Create the object """
-        threading.Thread.__init__(self)
-        self.cfusb = cfusb
-        self.in_queue = inQueue
-        self.sp = False
-        self.link_error_callback = link_error_callback
-        self.link_quality_callback = link_quality_callback
-
-    def stop(self):
-        """ Stop the thread """
-        self.sp = True
-        try:
-            self.join()
-        except Exception:
-            pass
-
-    def run(self):
-        """ Run the receiver thread """
-
-        while (True):
-            if (self.sp):
-                break
-            try:
-                # Blocking until USB data available
-                data = self.cfusb.receive_packet()
-                if len(data) > 0:
-                    pk = CRTPPacket(data[0], list(data[1:]))
-                    self.in_queue.put(pk)
-            except Exception as e:
-                import traceback
-
-                self.link_error_callback(
-                    "Error communicating with the Crazyflie"
-                    " ,it has probably been unplugged!\n"
-                    "Exception:%s\n\n%s" % (e,
-                                            traceback.format_exc()))
diff --git a/src/cflib/cflib/drivers/__init__.py b/src/cflib/cflib/drivers/__init__.py
deleted file mode 100644
index f074d797a973bcba4f86ae9ed1bcd86112840a72..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/drivers/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Drivers for the link interfaces that can be used by CRTP.
-"""
diff --git a/src/cflib/cflib/drivers/cfusb.py b/src/cflib/cflib/drivers/cfusb.py
deleted file mode 100644
index 8e620abf1900ae56e809db4ce89c728831fdb6e5..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/drivers/cfusb.py
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-USB driver for the Crazyflie.
-"""
-
-import os
-import usb
-import logging
-import sys
-import time
-import array
-import binascii
-
-__author__ = 'Bitcraze AB'
-__all__ = ['CfUsb']
-
-logger = logging.getLogger(__name__)
-
-USB_VID = 0x0483
-USB_PID = 0x5740
-
-try:
-    import usb.core
-
-    pyusb_backend = None
-    if os.name == "nt":
-        import usb.backend.libusb0 as libusb0
-
-        pyusb_backend = libusb0.get_backend()
-    pyusb1 = True
-except:
-    pyusb1 = False
-
-
-def _find_devices():
-    """
-    Returns a list of CrazyRadio devices currently connected to the computer
-    """
-    ret = []
-
-    logger.info("Looking for devices....")
-
-    if pyusb1:
-        for d in usb.core.find(idVendor=USB_VID, idProduct=USB_PID, find_all=1,
-                               backend=pyusb_backend):
-            ret.append(d)
-    else:
-        busses = usb.busses()
-        for bus in busses:
-            for device in bus.devices:
-                if device.idVendor == USB_VID:
-                    if device.idProduct == USB_PID:
-                        ret += [device, ]
-
-    return ret
-
-
-class CfUsb:
-    """ Used for communication with the Crazyradio USB dongle """
-
-    def __init__(self, device=None, devid=0):
-        """ Create object and scan for USB dongle if no device is supplied """
-        self.dev = None
-        self.handle = None
-        self._last_write = 0
-        self._last_read = 0
-
-        if device is None:
-            devices = _find_devices()
-            try:
-                self.dev = devices[devid]
-            except Exception:
-                self.dev = None
-
-        if self.dev:
-            if (pyusb1 is True):
-                self.dev.set_configuration(1)
-                self.handle = self.dev
-                self.version = float(
-                    "{0:x}.{1:x}".format(self.dev.bcdDevice >> 8,
-                                         self.dev.bcdDevice & 0x0FF))
-            else:
-                self.handle = self.dev.open()
-                self.handle.setConfiguration(1)
-                self.handle.claimInterface(0)
-                self.version = float(self.dev.deviceVersion)
-
-    def get_serial(self):
-        return usb.util.get_string(self.dev, 255, self.dev.iSerialNumber)
-
-    def close(self):
-        if (pyusb1 is False):
-            if self.handle:
-                self.handle.releaseInterface()
-                self.handle.reset()
-        else:
-            if self.dev:
-                self.dev.reset()
-
-        self.handle = None
-        self.dev = None
-
-    def scan(self):
-        # TODO: Currently only supports one device
-        if self.dev:
-            return [("usb://0", "")]
-        return []
-
-    def set_crtp_to_usb(self, crtp_to_usb):
-        if crtp_to_usb:
-            _send_vendor_setup(self.handle, 0x01, 0x01, 1, ())
-        else:
-            _send_vendor_setup(self.handle, 0x01, 0x01, 0, ())
-
-    # Data transfers
-    def send_packet(self, dataOut):
-        """ Send a packet and receive the ack from the radio dongle
-            The ack contains information about the packet transmition
-            and a data payload if the ack packet contained any """
-        try:
-            if (pyusb1 is False):
-                count = self.handle.bulkWrite(1, dataOut, 20)
-            else:
-                count = self.handle.write(endpoint=1, data=dataOut, timeout=20)
-        except usb.USBError as e:
-            pass
-
-    def receive_packet(self):
-        dataIn = ()
-        try:
-            if (pyusb1 is False):
-                dataIn = self.handle.bulkRead(0x81, 64, 20)
-            else:
-                dataIn = self.handle.read(0x81, 64, timeout=20)
-        except usb.USBError as e:
-            try:
-                if e.backend_error_code == -7 or e.backend_error_code == -116:
-                    # Normal, the read was empty
-                    pass
-                else:
-                    raise IOError("Crazyflie disconnected")
-            except AttributeError as e:
-                # pyusb < 1.0 doesn't implement getting the underlying error
-                # number and it seems as if it's not possible to detect
-                # if the cable is disconnected. So this detection is not
-                # supported, but the "normal" case will work.
-                pass
-
-        return dataIn
-
-
-# Private utility functions
-def _send_vendor_setup(handle, request, value, index, data):
-    if pyusb1:
-        handle.ctrl_transfer(usb.TYPE_VENDOR, request, wValue=value,
-                             wIndex=index, timeout=1000, data_or_wLength=data)
-    else:
-        handle.controlMsg(usb.TYPE_VENDOR, request, data, value=value,
-                          index=index, timeout=1000)
-
-
-def _get_vendor_setup(handle, request, value, index, length):
-    if pyusb1:
-        return handle.ctrl_transfer(usb.TYPE_VENDOR | 0x80, request,
-                                    wValue=value, wIndex=index, timeout=1000,
-                                    data_or_wLength=length)
-    else:
-        return handle.controlMsg(usb.TYPE_VENDOR | 0x80, request, length,
-                                 value=value, index=index, timeout=1000)
diff --git a/src/cflib/cflib/drivers/crazyradio.py b/src/cflib/cflib/drivers/crazyradio.py
deleted file mode 100644
index 9641fa23a0014bcc1c3b143e604a137684225402..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/drivers/crazyradio.py
+++ /dev/null
@@ -1,292 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-USB driver for the Crazyradio USB dongle.
-"""
-
-import os
-import usb
-import logging
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Crazyradio']
-
-logger = logging.getLogger(__name__)
-
-# USB parameters
-CRADIO_VID = 0x1915
-CRADIO_PID = 0x7777
-
-# Dongle configuration requests
-# See http://wiki.bitcraze.se/projects:crazyradio:protocol for documentation
-SET_RADIO_CHANNEL = 0x01
-SET_RADIO_ADDRESS = 0x02
-SET_DATA_RATE = 0x03
-SET_RADIO_POWER = 0x04
-SET_RADIO_ARD = 0x05
-SET_RADIO_ARC = 0x06
-ACK_ENABLE = 0x10
-SET_CONT_CARRIER = 0x20
-SCANN_CHANNELS = 0x21
-LAUNCH_BOOTLOADER = 0xFF
-
-try:
-    import usb.core
-
-    pyusb_backend = None
-    if os.name == "nt":
-        import usb.backend.libusb0 as libusb0
-
-        pyusb_backend = libusb0.get_backend()
-    pyusb1 = True
-except:
-    pyusb1 = False
-
-
-def _find_devices():
-    """
-    Returns a list of CrazyRadio devices currently connected to the computer
-    """
-    ret = []
-
-    if pyusb1:
-        for d in usb.core.find(idVendor=0x1915, idProduct=0x7777, find_all=1,
-                               backend=pyusb_backend):
-            ret.append(d)
-    else:
-        busses = usb.busses()
-        for bus in busses:
-            for device in bus.devices:
-                if device.idVendor == CRADIO_VID:
-                    if device.idProduct == CRADIO_PID:
-                        ret += [device, ]
-
-    return ret
-
-
-class _radio_ack:
-    ack = False
-    powerDet = False
-    retry = 0
-    data = ()
-
-
-class Crazyradio:
-    """ Used for communication with the Crazyradio USB dongle """
-    # configuration constants
-    DR_250KPS = 0
-    DR_1MPS = 1
-    DR_2MPS = 2
-
-    P_M18DBM = 0
-    P_M12DBM = 1
-    P_M6DBM = 2
-    P_0DBM = 3
-
-    def __init__(self, device=None, devid=0):
-        """ Create object and scan for USB dongle if no device is supplied """
-        if device is None:
-            try:
-                device = _find_devices()[devid]
-            except Exception:
-                raise Exception("Cannot find a Crazyradio Dongle")
-
-        self.dev = device
-
-        if (pyusb1 is True):
-            self.dev.set_configuration(1)
-            self.handle = self.dev
-            self.version = float("{0:x}.{1:x}".format(
-                self.dev.bcdDevice >> 8, self.dev.bcdDevice & 0x0FF))
-        else:
-            self.handle = self.dev.open()
-            self.handle.setConfiguration(1)
-            self.handle.claimInterface(0)
-            self.version = float(self.dev.deviceVersion)
-
-        if self.version < 0.3:
-            raise "This driver requires Crazyradio firmware V0.3+"
-
-        if self.version < 0.4:
-            logger.warning("You should update to Crazyradio firmware V0.4+")
-
-        # Reset the dongle to power up settings
-        self.set_data_rate(self.DR_2MPS)
-        self.set_channel(2)
-        self.arc = -1
-        if self.version >= 0.4:
-            self.set_cont_carrier(False)
-            self.set_address((0xE7,) * 5)
-            self.set_power(self.P_0DBM)
-            self.set_arc(3)
-            self.set_ard_bytes(32)
-
-    def close(self):
-        if (pyusb1 is False):
-            if self.handle:
-                self.handle.releaseInterface()
-                self.handle.reset()
-        else:
-            if self.dev:
-                self.dev.reset()
-
-        self.handle = None
-        self.dev = None
-
-    # Dongle configuration
-    def set_channel(self, channel):
-        """ Set the radio channel to be used """
-        _send_vendor_setup(self.handle, SET_RADIO_CHANNEL, channel, 0, ())
-
-    def set_address(self, address):
-        """ Set the radio address to be used"""
-        if len(address) != 5:
-            raise Exception("Crazyradio: the radio address shall be 5"
-                            " bytes long")
-
-        _send_vendor_setup(self.handle, SET_RADIO_ADDRESS, 0, 0, address)
-
-    def set_data_rate(self, datarate):
-        """ Set the radio datarate to be used """
-        _send_vendor_setup(self.handle, SET_DATA_RATE, datarate, 0, ())
-
-    def set_power(self, power):
-        """ Set the radio power to be used """
-        _send_vendor_setup(self.handle, SET_RADIO_POWER, power, 0, ())
-
-    def set_arc(self, arc):
-        """ Set the ACK retry count for radio communication """
-        _send_vendor_setup(self.handle, SET_RADIO_ARC, arc, 0, ())
-        self.arc = arc
-
-    def set_ard_time(self, us):
-        """ Set the ACK retry delay for radio communication """
-        # Auto Retransmit Delay:
-        # 0000 - Wait 250uS
-        # 0001 - Wait 500uS
-        # 0010 - Wait 750uS
-        # ........
-        # 1111 - Wait 4000uS
-
-        # Round down, to value representing a multiple of 250uS
-        t = int((us / 250) - 1)
-        if (t < 0):
-            t = 0
-        if (t > 0xF):
-            t = 0xF
-        _send_vendor_setup(self.handle, SET_RADIO_ARD, t, 0, ())
-
-    def set_ard_bytes(self, nbytes):
-        _send_vendor_setup(self.handle, SET_RADIO_ARD, 0x80 | nbytes, 0, ())
-
-    def set_cont_carrier(self, active):
-        if active:
-            _send_vendor_setup(self.handle, SET_CONT_CARRIER, 1, 0, ())
-        else:
-            _send_vendor_setup(self.handle, SET_CONT_CARRIER, 0, 0, ())
-
-    def _has_fw_scan(self):
-        # return self.version >= 0.5
-        # FIXME: Mitigation for Crazyradio firmware bug #9
-        return False
-
-    def scan_selected(self, selected, packet):
-        result = ()
-        for s in selected:
-            self.set_channel(s["channel"])
-            self.set_data_rate(s["datarate"])
-            status = self.send_packet(packet)
-            if status and status.ack:
-                result = result + (s,)
-
-        return result
-
-    def scan_channels(self, start, stop, packet):
-        if self._has_fw_scan():  # Fast firmware-driven scan
-            _send_vendor_setup(self.handle, SCANN_CHANNELS, start, stop,
-                               packet)
-            return tuple(_get_vendor_setup(self.handle, SCANN_CHANNELS,
-                                           0, 0, 64))
-        else:  # Slow PC-driven scan
-            result = tuple()
-            for i in range(start, stop + 1):
-                self.set_channel(i)
-                status = self.send_packet(packet)
-                if status and status.ack:
-                    result = result + (i,)
-            return result
-
-    # Data transferts
-    def send_packet(self, dataOut):
-        """ Send a packet and receive the ack from the radio dongle
-            The ack contains information about the packet transmition
-            and a data payload if the ack packet contained any """
-        ackIn = None
-        data = None
-        try:
-            if (pyusb1 is False):
-                self.handle.bulkWrite(1, dataOut, 1000)
-                data = self.handle.bulkRead(0x81, 64, 1000)
-            else:
-                self.handle.write(endpoint=1, data=dataOut, timeout=1000)
-                data = self.handle.read(0x81, 64, timeout=1000)
-        except usb.USBError:
-            pass
-
-        if data is not None:
-            ackIn = _radio_ack()
-            if data[0] != 0:
-                ackIn.ack = (data[0] & 0x01) != 0
-                ackIn.powerDet = (data[0] & 0x02) != 0
-                ackIn.retry = data[0] >> 4
-                ackIn.data = data[1:]
-            else:
-                ackIn.retry = self.arc
-
-        return ackIn
-
-
-# Private utility functions
-def _send_vendor_setup(handle, request, value, index, data):
-    if pyusb1:
-        handle.ctrl_transfer(usb.TYPE_VENDOR, request, wValue=value,
-                             wIndex=index, timeout=1000, data_or_wLength=data)
-    else:
-        handle.controlMsg(usb.TYPE_VENDOR, request, data, value=value,
-                          index=index, timeout=1000)
-
-
-def _get_vendor_setup(handle, request, value, index, length):
-    if pyusb1:
-        return handle.ctrl_transfer(usb.TYPE_VENDOR | 0x80, request,
-                                    wValue=value, wIndex=index, timeout=1000,
-                                    data_or_wLength=length)
-    else:
-        return handle.controlMsg(usb.TYPE_VENDOR | 0x80, request, length,
-                                 value=value, index=index, timeout=1000)
diff --git a/src/cflib/cflib/utils/__init__.py b/src/cflib/cflib/utils/__init__.py
deleted file mode 100644
index dd277b671ca49039c8196b9338e923d4dcd3b06e..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/utils/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Various utilities that is needed by the cflib.
-"""
diff --git a/src/cflib/cflib/utils/callbacks.py b/src/cflib/cflib/utils/callbacks.py
deleted file mode 100644
index 7a90f058a3e9d7fd1a88208642a455c5eeb860c5..0000000000000000000000000000000000000000
--- a/src/cflib/cflib/utils/callbacks.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2011-2013 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-"""
-Callback objects used in the Crazyflie library
-"""
-
-__author__ = 'Bitcraze AB'
-__all__ = ['Caller']
-
-
-class Caller():
-    """ An object were callbacks can be registered and called """
-
-    def __init__(self):
-        """ Create the object """
-        self.callbacks = []
-
-    def add_callback(self, cb):
-        """ Register cb as a new callback. Will not register duplicates. """
-        if ((cb in self.callbacks) is False):
-            self.callbacks.append(cb)
-
-    def remove_callback(self, cb):
-        """ Un-register cb from the callbacks """
-        self.callbacks.remove(cb)
-
-    def call(self, *args):
-        """ Call the callbacks registered with the arguments args """
-        for cb in self.callbacks:
-            cb(*args)
diff --git a/src/cflib/test/__init__.py b/src/cflib/test/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/cflib/test/crtp/__init__.py b/src/cflib/test/crtp/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/cflib/test/crtp/test_crtpstack.py b/src/cflib/test/crtp/test_crtpstack.py
deleted file mode 100644
index 1c45422e5bf1ceef8b546a915b59c12592c195a4..0000000000000000000000000000000000000000
--- a/src/cflib/test/crtp/test_crtpstack.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-import unittest
-
-from cflib.crtp.crtpstack import CRTPPacket
-
-
-class CRTPPacketTest(unittest.TestCase):
-
-    def setUp(self):
-        self.callback_count = 0
-        self.sut = CRTPPacket()
-
-    def test_that_port_and_channle_is_encoded_in_header(self):
-        # Fixture
-        self.sut.set_header(2, 1)
-
-        # Test
-        actual = self.sut.get_header()
-
-        # Assert
-        expected = 0x2d
-        self.assertEqual(expected, actual)
-
-    def test_that_port_is_truncated_in_header(self):
-        # Fixture
-        port = 0xff
-        self.sut.set_header(port, 0)
-
-        # Test
-        actual = self.sut.get_header()
-
-        # Assert
-        expected = 0xfc
-        self.assertEqual(expected, actual)
-
-    def test_that_channel_is_truncated_in_header(self):
-        # Fixture
-        channel = 0xff
-        self.sut.set_header(0, channel)
-
-        # Test
-        actual = self.sut.get_header()
-
-        # Assert
-        expected = 0x0f
-        self.assertEqual(expected, actual)
-
-    def test_that_port_and_channel_is_encoded_in_header_when_set_separat(self):
-        # Fixture
-        self.sut.port = 2
-        self.sut.channel = 1
-
-        # Test
-        actual = self.sut.get_header()
-
-        # Assert
-        expected = 0x2d
-        self.assertEqual(expected, actual)
-
-    def test_that_default_header_is_set_when_constructed(self):
-        # Fixture
-
-        # Test
-        actual = self.sut.get_header()
-
-        # Assert
-        expected = 0x0c
-        self.assertEqual(expected, actual)
-
-    def test_that_header_is_set_when_constructed(self):
-        # Fixture
-        sut = CRTPPacket(header=0x21)
-
-        # Test
-        actual = sut.get_header()
-
-        # Assert
-        self.assertEqual(0x2d, actual)
-        self.assertEqual(2, sut.port)
-        self.assertEqual(1, sut.channel)
diff --git a/src/cflib/test/utils/__init__.py b/src/cflib/test/utils/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/cflib/test/utils/test_callbacks.py b/src/cflib/test/utils/test_callbacks.py
deleted file mode 100644
index 649d4bd1aa1307207523885e761b08bab905b730..0000000000000000000000000000000000000000
--- a/src/cflib/test/utils/test_callbacks.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51 Franklin Street, Fifth Floor, Boston,
-#  MA  02110-1301, USA.
-
-import unittest
-
-from cflib.utils.callbacks import Caller
-
-
-class CallerTest(unittest.TestCase):
-
-    def setUp(self):
-        self.callback_count = 0
-        self.sut = Caller()
-
-    def test_that_callback_is_added(self):
-        # Fixture
-
-        # Test
-        self.sut.add_callback(self._callback)
-
-        # Assert
-        self.sut.call()
-        self.assertEqual(1, self.callback_count)
-
-    def test_that_callback_is_added_only_one_time(self):
-        # Fixture
-
-        # Test
-        self.sut.add_callback(self._callback)
-        self.sut.add_callback(self._callback)
-
-        # Assert
-        self.sut.call()
-        self.assertEqual(1, self.callback_count)
-
-    def test_that_multiple_callbacks_are_added(self):
-        # Fixture
-
-        # Test
-        self.sut.add_callback(self._callback)
-        self.sut.add_callback(self._callback2)
-
-        # Assert
-        self.sut.call()
-        self.assertEqual(2, self.callback_count)
-
-    def test_that_callback_is_removed(self):
-        # Fixture
-        self.sut.add_callback(self._callback)
-
-        # Test
-        self.sut.remove_callback(self._callback)
-
-        # Assert
-        self.sut.call()
-        self.assertEqual(0, self.callback_count)
-
-    def test_that_callback_is_called_with_arguments(self):
-        # Fixture
-        self.sut.add_callback(self._callback_with_args)
-
-        # Test
-        self.sut.call('The token')
-
-        # Assert
-        self.assertEqual('The token', self.callback_token)
-
-    def _callback(self):
-        self.callback_count += 1
-
-    def _callback2(self):
-        self.callback_count += 1
-
-    def _callback_with_args(self, token):
-        self.callback_token = token
diff --git a/src/cfloader/__init__.py b/src/cfloader/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..bee30992020a6e367e0e3a1fe3c33cfd3921f87f
--- /dev/null
+++ b/src/cfloader/__init__.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+#     ||          ____  _ __
+#  +------+      / __ )(_) /_______________ _____  ___
+#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
+#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
+#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
+#
+#  Copyright (C) 2011-2013 Bitcraze AB
+#
+#  Crazyflie Nano Quadcopter Client
+#
+#  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., 51 Franklin Street, Fifth Floor, Boston,
+#  MA  02110-1301, USA.
+
+# Crazy Loader bootloader utility
+# Can reset bootload and reset back the bootloader
+
+import sys
+
+import cflib.crtp
+from cflib.bootloader import Bootloader
+from cflib.bootloader.boottypes import BootVersion, TargetTypes
+
+
+def main():
+    # Initialise the CRTP link driver
+    link = None
+    try:
+        cflib.crtp.init_drivers()
+        link = cflib.crtp.get_link_driver("radio://")
+    except Exception as e:
+        print("Error: {}".format(str(e)))
+        if link:
+            link.close()
+        sys.exit(-1)
+
+    # Set the default parameters
+    clink = None
+    action = "info"
+    boot = "cold"
+
+    if len(sys.argv) < 2:
+        print()
+        print("==============================")
+        print(" CrazyLoader Flash Utility")
+        print("==============================")
+        print()
+        print(" Usage:", sys.argv[0], "[CRTP options] <action> [parameters]")
+        print()
+        print("The CRTP options are described above")
+        print()
+        print("Crazyload option:")
+        print("   info                    : Print the info of the bootloader "
+              "and quit.")
+        print("                             Will let the target in bootloader "
+              "mode")
+        print("   reset                   : Reset the device in firmware mode")
+        print("   flash <file> [targets]  : flash the <img> binary file from "
+              "the first")
+        print("                             possible  page in flash and reset "
+              "to firmware")
+        print("                             mode.")
+        if link:
+            link.close()
+        sys.exit(0)
+
+    # Analyse the command line parameters
+    sys.argv = sys.argv[1:]
+    argv = []
+
+    i = 0
+    while i < len(sys.argv):
+        if sys.argv[i] == "--cold-boot" or sys.argv[i] == "-c":
+            boot = "cold"
+        elif sys.argv[i] == "--warm-boot" or sys.argv[i] == "-w":
+            boot = "reset"
+            i += 1
+            clink = sys.argv[i]
+        else:
+            argv += [sys.argv[i]]
+        i += 1
+    sys.argv = argv
+
+    # Analyse the command
+    if len(sys.argv) < 1:
+        action = "info"
+    elif sys.argv[0] == "info":
+        action = "info"
+    elif sys.argv[0] == "reset":
+        action = "reset"
+    elif sys.argv[0] == "flash":
+        # print len(sys.argv)
+        if len(sys.argv) < 2:
+            print("The flash action require a file name.")
+            link.close()
+            sys.exit(-1)
+        action = "flash"
+        filename = sys.argv[1]
+        targetnames = {}
+        for t in sys.argv[2:]:
+            [target, type] = t.split("-")
+            if target in targetnames:
+                targetnames[target] += (type,)
+            else:
+                targetnames[target] = (type,)
+    else:
+        print("Action", sys.argv[0], "unknown!")
+        link.close()
+        sys.exit(-1)
+
+    # Currently there's two different targets available
+    targets = ()
+
+    try:
+        # Initialise the bootloader lib
+        bl = Bootloader(clink)
+
+        #########################################
+        # Get the connection with the bootloader
+        #########################################
+        # The connection is done by reseting to the bootloader (default)
+        if boot == "reset":
+            print("Reset to bootloader mode ..."),
+            sys.stdout.flush()
+            if bl.start_bootloader(warm_boot=True):
+                print(" done!")
+            else:
+                print("Failed to warmboot")
+                bl.close()
+                sys.exit(-1)
+        else:  # The connection is done by a cold boot ...
+            print("Restart the Crazyflie you want to bootload in the next"),
+            print(" 10 seconds ..."),
+
+            sys.stdout.flush()
+            if bl.start_bootloader(warm_boot=False):
+                print(" done!")
+            else:
+                print("Cannot connect the bootloader!")
+                bl.close()
+                sys.exit(-1)
+
+        print("Connected to bootloader on {} (version=0x{:X})".format(
+            BootVersion.to_ver_string(bl.protocol_version),
+            bl.protocol_version))
+
+        if bl.protocol_version == BootVersion.CF2_PROTO_VER:
+            targets += (bl.get_target(TargetTypes.NRF51),)
+        targets += (bl.get_target(TargetTypes.STM32),)
+
+        ######################################
+        # Doing something (hopefully) useful
+        ######################################
+
+        # Print information about the targets
+        for target in targets:
+            print(target)
+        if action == "info":
+            None  # Already done ...
+        elif action == "reset":
+            print
+            print("Reset in firmware mode ...")
+            bl.reset_to_firmware()
+        elif action == "flash":
+            bl.flash(filename, targetnames)
+            print("Reset in firmware mode ...")
+            bl.reset_to_firmware()
+        else:
+            None
+    except Exception as e:
+        import traceback
+
+        traceback.print_exc(file=sys.stdout)
+        print(e)
+
+    finally:
+        #########################
+        # Closing the connection
+        #########################
+        if bl:
+            bl.close()
diff --git a/src/cfloader/__main__.py b/src/cfloader/__main__.py
new file mode 100644
index 0000000000000000000000000000000000000000..b48e88c16bd98d4344f120ef78ca50605a006e1d
--- /dev/null
+++ b/src/cfloader/__main__.py
@@ -0,0 +1,4 @@
+from cfloader import main
+
+if __name__ == "__main__":
+    main()
diff --git a/src/cfzmq.py b/src/cfzmq/__init__.py
similarity index 98%
rename from src/cfzmq.py
rename to src/cfzmq/__init__.py
index 46c2969e0fe68857fcaf425f778ffb3adc584058..c336f6604a02dc6022ae5a9f2282cb07ca1098c1 100644
--- a/src/cfzmq.py
+++ b/src/cfzmq/__init__.py
@@ -40,6 +40,8 @@ import cflib.crtp
 from cflib.crazyflie import Crazyflie
 from cflib.crazyflie.log import LogConfig
 
+import cfclient
+
 if os.name == 'posix':
     print('Disabling standard output for libraries!')
     stdout = os.dup(1)
@@ -72,6 +74,7 @@ logger = logging.getLogger(__name__)
 
 
 class _SrvThread(Thread):
+
     def __init__(self, socket, log_socket, param_socket, conn_socket, cf,
                  *args):
         super(_SrvThread, self).__init__(*args)
@@ -298,6 +301,7 @@ class _SrvThread(Thread):
 
 
 class _CtrlThread(Thread):
+
     def __init__(self, socket, cf, *args):
         super(_CtrlThread, self).__init__(*args)
         self._socket = socket
@@ -316,8 +320,8 @@ class ZMQServer():
     def __init__(self, base_url):
         """Start threads and bind ports"""
         cflib.crtp.init_drivers(enable_debug_driver=True)
-        self._cf = Crazyflie(ro_cache=sys.path[0] + "/cflib/cache",
-                             rw_cache=sys.path[1] + "/cache")
+        self._cf = Crazyflie(ro_cache=None,
+                             rw_cache=cfclient.config_path + "/cache")
 
         signal.signal(signal.SIGINT, signal.SIG_DFL)
 
@@ -366,3 +370,6 @@ def main():
     ZMQServer(args.url)
 
     # CRTL-C to exit
+
+if __name__ == "__main__":
+    main()
diff --git a/src/cfzmq/__main__.py b/src/cfzmq/__main__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ba7f561c929f5e5fc86d6ae3af0429152bdf91a
--- /dev/null
+++ b/src/cfzmq/__main__.py
@@ -0,0 +1,4 @@
+from cfzmq import main
+
+if __name__ == "__main__":
+    main()
diff --git a/src/leapsdk/__init__.py b/src/leapsdk/__init__.py
deleted file mode 100644
index c8c34c858acc3dda7dcfff26944fa8f1ee86ba22..0000000000000000000000000000000000000000
--- a/src/leapsdk/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-#     ||          ____  _ __
-#  +------+      / __ )(_) /_______________ _____  ___
-#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
-#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
-#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
-#
-#  Copyright (C) 2014 Bitcraze AB
-#
-#  Crazyflie Nano Quadcopter Client
-#
-#  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., 51
-#  Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
-"""
-In order to use the Leap Motion as an input device reader the libraries from
-the Leap Motion SDK has to be placed in this directory. This can be done by
-downloading the SDK from the http://developer.leapmotion.com website, unpacking
-it and copying the following files:
-
-  * LeapSDK\lib\Leap.py                     -> leapsdk\Leap.py
-  * LeapSDK\lib\<your_arch>\LeapPython.so   -> leapsdk\LeapPython.so
-  * LeapSDK\lib\<your_arch>\libLeap.so      -> leapsdk\libLeap.so
-"""
diff --git a/tools/build/bdist b/tools/build/bdist
new file mode 100755
index 0000000000000000000000000000000000000000..ed4f310909c5a426c0fedd507470fa8cfabd5eaa
--- /dev/null
+++ b/tools/build/bdist
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+import os
+import subprocess
+import os.path as _path
+
+__author__ = 'arnaud'
+
+try:
+    script_dir = os.path.dirname(os.path.realpath(__file__))
+    root = _path.normpath(_path.join(script_dir, '../..'))
+
+    subprocess.check_call(['python3', 'setup.py', 'bdist_wheel'], cwd=root)
+
+    print("Wheel built")
+except subprocess.CalledProcessError as e:
+    print("Error: Cannot build the wheel")
+    raise e
diff --git a/tools/build/build b/tools/build/build
index 393ccc3d2efd160003dc907b15b5baaed8c35810..065f42f27b5e535daf7d2a6f689ceda4966a5060 100755
--- a/tools/build/build
+++ b/tools/build/build
@@ -4,5 +4,5 @@ import subprocess
 
 script_dir = os.path.dirname(os.path.realpath(__file__))
 
-subprocess.check_call([script_dir + "/pep8"])
-subprocess.check_call([script_dir + "/test"])
+subprocess.check_call([script_dir + "/flake8"])
+subprocess.check_call([script_dir + "/bdist"])
diff --git a/tools/build/pep8 b/tools/build/flake8
similarity index 60%
rename from tools/build/pep8
rename to tools/build/flake8
index 162f8fea0f7d6197b372112dfe9f7902f8d301a9..3f795f6620a03826033cd4bd41de544c091e4abf 100755
--- a/tools/build/pep8
+++ b/tools/build/flake8
@@ -6,11 +6,12 @@ __author__ = 'kristoffer'
 
 
 def _check_files_without_ext(path):
-    subprocess.check_call(["pep8", "--statistics", "--filename=*", path])
+    subprocess.check_call(["python3", "-m", "flake8.run", "--filename=*",
+                           path])
 
 
 def _check_files_with_ext(path):
-    subprocess.check_call(["pep8", "--statistics", path])
+    subprocess.check_call(["python3", "-m", "flake8.run", path])
 
 
 try:
@@ -19,7 +20,7 @@ try:
     _check_files_without_ext(script_dir)
     _check_files_with_ext(script_dir + "/../..")
 
-    print("PEP8 check pass")
+    print("Flake8 check pass")
 except subprocess.CalledProcessError as e:
-    print("Error: PEP8 check fail")
+    print("Error: Flake8 check fail")
     raise e
diff --git a/tools/build/prep_windows b/tools/build/prep_windows
new file mode 100644
index 0000000000000000000000000000000000000000..db498d04a0b67fd5c01037e574c71b52ca0736ae
--- /dev/null
+++ b/tools/build/prep_windows
@@ -0,0 +1,27 @@
+# Download and decompress SDL2 for Windows
+import urllib.request
+import os
+from zipfile import ZipFile
+
+url = 'https://www.libsdl.org/release/SDL2-2.0.4-win32-x86.zip'
+dllpath = os.path.join("src", 'cfclient', 'third_party')
+
+
+def main():
+    print("Downloading SDL2 from {} ...".format(url))
+    response = urllib.request.urlopen(url)
+    zipdata = response.read()
+    if not os.path.exists('build'):
+        os.makedirs('build')
+    with open(os.path.join('build', 'sdl.zip'), 'wb') as f:
+        f.write(zipdata)
+
+    print("Unziping SDL2.dll in src/cfclient/third_party")
+    if not os.path.exists(dllpath):
+        os.makedirs(dllpath)
+    with ZipFile(os.path.join('build', 'sdl.zip'), 'r') as z:
+        z.extract('SDL2.dll', dllpath)
+        z.extract('README-SDL.txt', dllpath)
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/build/test b/tools/build/test
deleted file mode 100755
index facc77f7f6faf6c368ab95be20340b5ccf227f09..0000000000000000000000000000000000000000
--- a/tools/build/test
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-import os
-import subprocess
-import os.path as _path
-
-try:
-    script_dir = os.path.dirname(os.path.realpath(__file__))
-    cflib = _path.normpath(_path.join(script_dir, '../../src/cflib'))
-
-    subprocess.check_call(['python', '-m', 'unittest', 'discover', cflib])
-
-    print("Unit tests pass")
-except subprocess.CalledProcessError as e:
-    print("Error: Unit tests fail")
-    raise e
diff --git a/win32install/cfclient.nsi.tmpl b/win32install/cfclient.nsi.tmpl
index 1f8cb6077cb00cd335b3be42a5a9f28a47a2c927..d577ae49433b97bbbff1f437e6848f7586332a50 100644
--- a/win32install/cfclient.nsi.tmpl
+++ b/win32install/cfclient.nsi.tmpl
@@ -1,136 +1,136 @@
-; Script based on example2.nsi, converted to MUI2
-
-;--------------------------------
-SetCompressor /SOLID /FINAL lzma
-
-!include "MUI2.nsh"
-
-; The name of the installer
-Name "Crazyflie PC client {{version}}"
-
-; The file to write
-OutFile "cfclient-win32-install-{{version}}.exe"
-
-; The default installation directory
-InstallDir "$PROGRAMFILES\Crazyflie client"
-
-; Registry key to check for directory (so if you install again, it will 
-; overwrite the old one automatically)
-InstallDirRegKey HKLM "Software\Crazyflie_client" "Install_Dir"
-
-; Request application privileges for Windows Vista
-RequestExecutionLevel admin
-
-;--------------------------------
-;Interface Settings
-
-  !define MUI_ABORTWARNING
-
-;--------------------------------
-;Pages
-
-!insertmacro MUI_PAGE_WELCOME
-!define MUI_PAGE_CUSTOMFUNCTION_SHOW licpageshow
-!insertmacro MUI_PAGE_LICENSE "..\LICENSE.txt"
-!insertmacro MUI_PAGE_COMPONENTS
-!insertmacro MUI_PAGE_DIRECTORY
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-
-!insertmacro MUI_UNPAGE_WELCOME
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-!insertmacro MUI_UNPAGE_FINISH
-
-; Function to display license in monospace font
-Function licpageshow
-FindWindow $0 "#32770" "" $HWNDPARENT
-CreateFont $1 "Courier New" "$(^FontSize)"
-GetDlgItem $0 $0 1000
-SendMessage $0 ${WM_SETFONT} $1 1
-FunctionEnd
-  
-;--------------------------------
-;Languages
- 
-  !insertmacro MUI_LANGUAGE "English"
-
-;--------------------------------
-
-; The stuff to install
-Section "Crazyflie Client" SecCfclient
-
-  SectionIn RO
-  
-  ; Set output path to the installation directory.
-  SetOutPath $INSTDIR
-  
-  ; Create folders
-  {% for dir in dirs %}
-    CreateDirectory "$INSTDIR\{{dir}}"
-  {% endfor %}
-  
-  ; Files to install
-  {% for file in files %}
-    File "/oname=$INSTDIR\{{file}}" "..\dist\{{file}}"
-  {% endfor %}
-  
-  ; Write the installation path into the registry
-  WriteRegStr HKLM SOFTWARE\Crazyflie_client "Install_Dir" "$INSTDIR"
-  
-  ;Write Start menu items
-  CreateDirectory "$SMPROGRAMS\Crazyflie client"
-  CreateShortCut "$SMPROGRAMS\Crazyflie client\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
-  CreateShortCut "$SMPROGRAMS\Crazyflie client\Crazyflie PC client.lnk" "$INSTDIR\cfclient.exe" "" "$INSTDIR\cfclient.exe" 0
-  
-  ; Write the uninstall keys for Windows
-  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "DisplayName" "Crazyflie Client"
-  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "UninstallString" '"$INSTDIR\uninstall.exe"'
-  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "NoModify" 1
-  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "NoRepair" 1
-  WriteUninstaller "uninstall.exe"
-  
-SectionEnd
-
-; Optional section (can be disabled by the user)
-;Section "Desktop Shortcuts"
-;
-;SectionEnd
-
-;--------------------------------
-;Descriptions
-
-  ;Language strings
-  LangString DESC_SecCfclient ${LANG_ENGLISH} "Crazyflie PC Client"
-
-  ;Assign language strings to sections
-  !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
-    !insertmacro MUI_DESCRIPTION_TEXT ${SecCfclient} $(DESC_SecCfclient)
-  !insertmacro MUI_FUNCTION_DESCRIPTION_END
-
-;--------------------------------
-
-; Uninstaller
-
-Section "Uninstall"
-  
-  ; Remove registry keys
-  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient"
-  DeleteRegKey HKLM SOFTWARE\Crazyflie_client
-
-  ; Remove files and uninstaller
-  {% for file in files %}
-    Delete "$INSTDIR\{{file}}"
-  {% endfor %}
-  Delete $INSTDIR\uninstall.exe
-
-  ; Remove shortcuts, if any
-  Delete "$SMPROGRAMS\Crazyflie client\*.*"
-
-  ; Remove directories used
-  RMDir "$SMPROGRAMS\Crazyflie client"
-  {% for dir in dirs|reverse %}
-    RMDir "$INSTDIR\{{dir}}"
-  {% endfor %}
-
-SectionEnd
+; Script based on example2.nsi, converted to MUI2
+
+;--------------------------------
+SetCompressor /SOLID /FINAL lzma
+
+!include "MUI2.nsh"
+
+; The name of the installer
+Name "Crazyflie PC client {{version}}"
+
+; The file to write
+OutFile "cfclient-win32-install-{{version}}.exe"
+
+; The default installation directory
+InstallDir "$PROGRAMFILES\Crazyflie client"
+
+; Registry key to check for directory (so if you install again, it will
+; overwrite the old one automatically)
+InstallDirRegKey HKLM "Software\Crazyflie_client" "Install_Dir"
+
+; Request application privileges for Windows Vista
+RequestExecutionLevel admin
+
+;--------------------------------
+;Interface Settings
+
+  !define MUI_ABORTWARNING
+
+;--------------------------------
+;Pages
+
+!insertmacro MUI_PAGE_WELCOME
+!define MUI_PAGE_CUSTOMFUNCTION_SHOW licpageshow
+!insertmacro MUI_PAGE_LICENSE "..\LICENSE.txt"
+!insertmacro MUI_PAGE_COMPONENTS
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_WELCOME
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+!insertmacro MUI_UNPAGE_FINISH
+
+; Function to display license in monospace font
+Function licpageshow
+FindWindow $0 "#32770" "" $HWNDPARENT
+CreateFont $1 "Courier New" "$(^FontSize)"
+GetDlgItem $0 $0 1000
+SendMessage $0 ${WM_SETFONT} $1 1
+FunctionEnd
+
+;--------------------------------
+;Languages
+
+  !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+
+; The stuff to install
+Section "Crazyflie Client" SecCfclient
+
+  SectionIn RO
+
+  ; Set output path to the installation directory.
+  SetOutPath $INSTDIR
+
+  ; Create folders
+  {% for dir in dirs %}
+    CreateDirectory "$INSTDIR\{{dir}}"
+  {% endfor %}
+
+  ; Files to install
+  {% for file in files %}
+    File "/oname=$INSTDIR\{{file}}" "..\dist\{{file}}"
+  {% endfor %}
+
+  ; Write the installation path into the registry
+  WriteRegStr HKLM SOFTWARE\Crazyflie_client "Install_Dir" "$INSTDIR"
+
+  ;Write Start menu items
+  CreateDirectory "$SMPROGRAMS\Crazyflie client"
+  CreateShortCut "$SMPROGRAMS\Crazyflie client\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
+  CreateShortCut "$SMPROGRAMS\Crazyflie client\Crazyflie PC client.lnk" "$INSTDIR\cfclient.exe" "" "$INSTDIR\cfclient.exe" 0
+
+  ; Write the uninstall keys for Windows
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "DisplayName" "Crazyflie Client"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "UninstallString" '"$INSTDIR\uninstall.exe"'
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "NoModify" 1
+  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient" "NoRepair" 1
+  WriteUninstaller "uninstall.exe"
+
+SectionEnd
+
+; Optional section (can be disabled by the user)
+;Section "Desktop Shortcuts"
+;
+;SectionEnd
+
+;--------------------------------
+;Descriptions
+
+  ;Language strings
+  LangString DESC_SecCfclient ${LANG_ENGLISH} "Crazyflie PC Client"
+
+  ;Assign language strings to sections
+  !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+    !insertmacro MUI_DESCRIPTION_TEXT ${SecCfclient} $(DESC_SecCfclient)
+  !insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+;--------------------------------
+
+; Uninstaller
+
+Section "Uninstall"
+
+  ; Remove registry keys
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cfclient"
+  DeleteRegKey HKLM SOFTWARE\Crazyflie_client
+
+  ; Remove files and uninstaller
+  {% for file in files %}
+    Delete "$INSTDIR\{{file}}"
+  {% endfor %}
+  Delete $INSTDIR\uninstall.exe
+
+  ; Remove shortcuts, if any
+  Delete "$SMPROGRAMS\Crazyflie client\*.*"
+
+  ; Remove directories used
+  RMDir "$SMPROGRAMS\Crazyflie client"
+  {% for dir in dirs|reverse %}
+    RMDir "$INSTDIR\{{dir}}"
+  {% endfor %}
+
+SectionEnd
diff --git a/win32install/generate_nsis.py b/win32install/generate_nsis.py
index f3e9f3486751b6fa986c6e5522d2c81a1b756c12..f79230c74b3a5e03020a02c9e562843455d40ad7 100644
--- a/win32install/generate_nsis.py
+++ b/win32install/generate_nsis.py
@@ -1,8 +1,11 @@
-import jinja2
+# -*- coding: utf-8 -*-
 import os
-from subprocess import Popen, PIPE
+from subprocess import PIPE
+from subprocess import Popen
+
+import jinja2
 
-DIST_PATH = "..\dist"
+DIST_PATH = "..\\dist"
 
 # Get list of files and directory to install/uninstall
 INSTALL_FILES = []
@@ -26,11 +29,11 @@ try:
 except OSError:
     raise Exception("Cannot run git: Git is required to generate installer!")
 
-VERSION = output.strip()
+VERSION = output.strip().decode("utf-8")
 
 print("Cfclient version {}".format(VERSION))
 
-os.chdir(os.path.dirname(__file__))
+os.chdir("..\\win32install")
 
 with open("cfclient.nsi.tmpl", "r") as template_file:
     TEMPLATE = template_file.read()
diff --git a/win32install/readme.txt b/win32install/readme.txt
deleted file mode 100644
index 92441ee95675c75e692b4821569ca2008798c3e3..0000000000000000000000000000000000000000
--- a/win32install/readme.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-Warning: Generating windows executable is not working yet with Python3. This is
-work in progress in issue #207. Any help is apreciated!
-
-Howto generate cfclient Windows installer
-=========================================
-
-The windows installer is generated using the NSIS installer system. The steps
-to generate the distribution are:
- - Clone a clean copy of the repos
- - Generate and test Windows executable
- - Generate the installer script
- - Build the installer
-
-All the procedure has to be run on Windows. Tested on Windows 7. A release
-version should have the right version written to setup.py (ie. not a
-development version).
-
-Prerequisites
--------------
-Should be all from source install + the following:
- - [Python 3.4](https://www.python.org/downloads/windows/) (make sure the pip component is selected when installing)
- - [Nsis 2.46](http://nsis.sourceforge.net/Download)
- - [GIT](https://git-scm.com/download/win)
-
-Install the following with pip:
-```
-\Python34\python.exe -m pip install jinja2 py2exe
-```
-
-Procedure
----------
-Clone the cfclient repos in a new folder and update it to the (tagged) version you
-want to generate.
-
-Locate MSVCP90.dll in your pc and copy it in the source folder. There may be many
-version, the good one is 9.0.21022.8 and has a size of 555kB. If not installed
-read py2exe doc to download the Microsoft visual C++ 2008 redistributable package.
-
-Run in a command line window:
-> cd <path_to_crazyflie_pc_client>
-> setup.py py2exe
-
-Test and validate the new executable by running:
-> dist\cfclient
-
-Generate the installer configuration:
-> cd win32install
-> generate_nsis.py
- Found 516 files in 41 folders to install.
- Cfclient version 2013.4.1
-
-Finally open the win32install folder in the file explorer. Right click on
-cfclient.nsi, chose "Compile NSIS script (choose compressor)". The NSIS
-compiler opens, Select "LZMA (solid)" compressor. After a little while
-the script is compiled and "cfclient-win32-install-version.exe" is created
-in the script folder.