├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bit_decoder.h ├── data_logger.c ├── data_logger.h ├── logging.c ├── logging.h ├── main.c ├── nrz_decode.c ├── nrz_decode.h ├── sample_decoder.h ├── stream_decoder.h ├── temp-daemon.sh ├── tools.c ├── tools.h ├── transmission.c ├── transmission.h ├── tx29.c ├── tx29.h ├── ws300.c └── ws300.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | rtl_868 3 | temp-*.csv 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # rtl_868 3 | # Copyright (C) 2015 Clemens Helfmeier 4 | # e-mail: clemenshelfmeier@gmx.de 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along 17 | # with this program; if not, write to the Free Software Foundation, Inc., 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | 20 | # for debugging 21 | # CFLAGS += -ggdb 22 | LDFLAGS += -lrt 23 | 24 | rtl_868: ws300.o transmission.o nrz_decode.o main.o logging.o tx29.o tools.o data_logger.o 25 | ${CC} ${LDFLAGS} $^ -o $@ 26 | 27 | %.lss: % 28 | objdump -xS $< > $@ 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rtl_868 2 | Reciever software for FM modulated temperature stations. 3 | 4 | compile: 'make' 5 | run: rtl_fm -f 868.26e6 -M fm -s 500k -r 75k -g 42 -A fast | ./rtl_868 > dump-file.txt 6 | 7 | -------------------------------------------------------------------------------- /bit_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef BIT_DECODER_H 22 | #define BIT_DECODER_H 1 23 | 24 | #include "stream_decoder.h" 25 | 26 | /* interface for bit decoder */ 27 | typedef struct { 28 | char *name; 29 | char *shorthand; 30 | // interface 31 | int (*init)(stream_decoder_t *next); 32 | int (*input)(int transmission[], unsigned int length, int noise, int signal); 33 | } bit_decoder_t; 34 | 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /data_logger.c: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #include "logging.h" 22 | #include "data_logger.h" 23 | #include 24 | #include 25 | 26 | /// time at start of program 27 | time_t dl_file_start; 28 | 29 | /// file to write to 30 | FILE *dl_file_out; 31 | 32 | int dl_file_init( FILE *out ) { 33 | time( &dl_file_start ); 34 | dl_file_out = out; 35 | logging_info( "Data_Logger initialized.\n" ); 36 | } 37 | 38 | int dl_file_input(int sensor_id, float temp, float rel_hum, int flags) { 39 | /* output into octave readable file */ 40 | /* decorate with timestamp and seconds since start of program */ 41 | 42 | time_t cur_time; 43 | struct tm ts; 44 | if ((time( &cur_time ) == 0) || (localtime_r(&cur_time, &ts) == 0)) { 45 | logging_error( "Could not get current time.\n" ); 46 | ts.tm_year = 0; ts.tm_mon = 0; ts.tm_mday = 0; 47 | ts.tm_hour = 0; ts.tm_min = 0; ts.tm_sec = 0; 48 | } 49 | double time_sec = difftime( cur_time, dl_file_start ); 50 | 51 | logging_info( "%04i-%02i-%02i %02i:%02i:%02i, %lli, %i, %1.2f, %1.2f, %i.\n", ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, (long long int)cur_time, sensor_id, temp, rel_hum, flags ); 52 | if (rel_hum == 106) { 53 | fprintf( dl_file_out, "%04i-%02i-%02i %02i:%02i:%02i, %lli, %i, %1.2f, nan, %i.\n", ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, (long long int)cur_time, sensor_id, temp, flags ); 54 | } else { 55 | fprintf( dl_file_out, "%04i-%02i-%02i %02i:%02i:%02i, %lli, %i, %1.2f, %1.2f, %i.\n", ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, (long long int)cur_time, sensor_id, temp, rel_hum, flags ); 56 | } 57 | fflush( dl_file_out ); 58 | 59 | logging_status( 3, "%i -> %1.1f°C, %1.1f%%", sensor_id, temp, rel_hum ); 60 | return 0; // ok :-) 61 | } 62 | 63 | data_logger_t dl_file = { 64 | .name = "DataLogger writing to file", 65 | .shorthand = "dl_file", 66 | .init = dl_file_init, 67 | .input = dl_file_input, 68 | }; 69 | -------------------------------------------------------------------------------- /data_logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #ifndef DATA_LOGGER_H 23 | #define DATA_LOGGER_H 1 24 | 25 | #include 26 | 27 | /* interface for bit decoder */ 28 | typedef struct { 29 | char *name; 30 | char *shorthand; 31 | // interface 32 | int (*init)(FILE *out); 33 | int (*input)(int sensor_id, float temp, float rel_hum, int flags); 34 | } data_logger_t; 35 | 36 | extern data_logger_t dl_file; 37 | 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /logging.c: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | int verbose = 0; 26 | int l_n = 0; 27 | 28 | #define LOGGING_MODULES 16 29 | #define LOGGING_LENGTH 256 30 | char l_status[LOGGING_MODULES][LOGGING_LENGTH]; 31 | 32 | void logging_init(void) { 33 | int i; 34 | for (i = 0; i 0) { fprintf( stderr, " " ); l_n--; } 41 | fprintf( stderr, "\r" ); 42 | } 43 | void logging_restatus(void){ 44 | int i; 45 | logging_destatus(); 46 | for (i = 0; i= LOGGING_MODULES) || (module < 0) || (verbose < 0)) return; 52 | va_list argp; 53 | va_start(argp, f); 54 | if (vsprintf( l_status[module], f, argp ) < 0) 55 | l_status[module][0] = 0; 56 | va_end(argp); 57 | } 58 | 59 | void _logging_verbose( const char* f, ... ) { 60 | if (verbose > 3) { 61 | logging_destatus(); 62 | va_list argp; 63 | va_start(argp, f); 64 | vfprintf( stderr, f, argp ); 65 | va_end(argp); 66 | } 67 | } 68 | void _logging_info( const char* f, ... ) { 69 | if (verbose > 2) { 70 | logging_destatus(); 71 | va_list argp; 72 | va_start(argp, f); 73 | vfprintf( stderr, f, argp ); 74 | va_end(argp); 75 | } 76 | } 77 | void _logging_warning( const char* f, ... ) { 78 | if (verbose > 1) { 79 | logging_destatus(); 80 | va_list argp; 81 | va_start(argp, f); 82 | vfprintf( stderr, f, argp ); 83 | va_end(argp); 84 | } 85 | } 86 | void _logging_error( const char* f, ... ) { 87 | if (verbose > 0) { 88 | logging_destatus(); 89 | va_list argp; 90 | va_start(argp, f); 91 | vfprintf( stderr, f, argp ); 92 | va_end(argp); 93 | } 94 | } 95 | void _logging_message( const char* f, ... ) { 96 | if (verbose > -1) { 97 | logging_destatus(); 98 | va_list argp; 99 | va_start(argp, f); 100 | vfprintf( stderr, f, argp ); 101 | va_end(argp); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /logging.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #ifndef LOGGING_H 23 | #define LOGGING_H 1 24 | 25 | extern int verbose; 26 | #define LOGGING_STRR(arg) #arg 27 | #define LOGGING_STR(arg) LOGGING_STRR( arg ) 28 | 29 | #define logging_verbose( args... ) do { _logging_verbose( "V: " __FILE__ ":" LOGGING_STR(__LINE__) ": " args ); } while (0) 30 | #define logging_info( args... ) do { _logging_info( "I: " __FILE__ ":" LOGGING_STR(__LINE__) ": " args ); } while (0) 31 | #define logging_warning( args... ) do { _logging_warning( "W: " __FILE__ ":" LOGGING_STR(__LINE__) ": " args ); } while (0) 32 | #define logging_error( args... ) do { _logging_error( "E: " __FILE__ ":" LOGGING_STR(__LINE__) ": " args ); } while (0) 33 | #define logging_message( args... ) do { _logging_mesage( args ); } while (0) 34 | #define logging_status( n, str, args... ) do { _logging_status( n, str "; ", args ); } while (0) 35 | 36 | void logging_restatus(void); 37 | void _logging_status(int module, const char* f, ... ); 38 | void _logging_verbose( const char* f, ... ); 39 | void _logging_info( const char* f, ... ); 40 | void _logging_warning( const char* f, ... ); 41 | void _logging_error( const char* f, ... ); 42 | void _logging_message( const char* f, ... ); 43 | void logging_init(void); 44 | 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #include "nrz_decode.h" 23 | #include "transmission.h" 24 | #include "ws300.h" 25 | #include "logging.h" 26 | #include "tx29.h" 27 | #include "data_logger.h" 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | int data_to_string( float data, float* base, char* cexp ) { 41 | // convert the value of data to base + exponent notation 42 | int exp = 0; 43 | while ((data > (1<<10)) && (exp < 4)) { 44 | data /= (1<<10); 45 | exp++; 46 | } 47 | while ((data < 1) && (exp > -4)) { 48 | data *= (1<<10); 49 | exp--; 50 | } 51 | char lexp[] = "pnum kMGT"; 52 | *cexp = lexp[ exp + 4 ]; 53 | *base = data; 54 | return 1; 55 | } 56 | 57 | FILE *in, *out; 58 | int duplicate_stream_input( int transmission[], unsigned int length ) { 59 | if ((ws300.input( transmission, length) == 0) || 60 | (tx29.input(transmission, length) == 0)) 61 | return 0; 62 | else if (verbose > 1) { 63 | if (length < 6) return -1; 64 | fprintf( out, "__, %i, ", length ); 65 | while (length-- > 0) 66 | fprintf( out, "%02x ", *transmission++ ); 67 | fprintf( out, "\n" ); 68 | fflush(out); 69 | return 0; 70 | } else { 71 | return 0; 72 | } 73 | } 74 | 75 | int main (int argc, char **argv) { 76 | 77 | char* filename = 0; 78 | char* outfilename = 0; 79 | int c; 80 | 81 | logging_init(); 82 | 83 | opterr = 0; 84 | 85 | while ((c = getopt (argc, argv, "vqf:o:")) != -1) 86 | switch (c) 87 | { 88 | case 'v': 89 | verbose++; 90 | break; 91 | case 'q': 92 | verbose--; 93 | break; 94 | case 'f': 95 | if (filename != 0) { 96 | logging_info( "Overriding previous -f flag '%s' with '%s'.\n", filename, optarg ); 97 | } 98 | filename = optarg; 99 | break; 100 | case 'o': 101 | if (outfilename != 0) { 102 | logging_info( "Overriding previous -o flag '%s' with '%s'.\n", outfilename, optarg ); 103 | } 104 | outfilename = optarg; 105 | break; 106 | case '?': 107 | if ((optopt == 'f') || (optopt == 'o') || (optopt == 'd')) 108 | fprintf (stderr, "Option -%c requires an argument.\n", optopt); 109 | else if (isprint (optopt)) 110 | fprintf (stderr, "Unknown option `-%c'.\n", optopt); 111 | else 112 | fprintf (stderr, 113 | "Unknown option character `\\x%x'.\n", 114 | optopt); 115 | fprintf( stderr, 116 | "rtl_868, Copyright (C) 2015 Clemens Helfmeier\n" 117 | "rtl_868 comes with ABSOLUTELY NO WARRANTY; for details see the\n" 118 | "LICENSE file distributed with the program.\n" 119 | "This is free software, and you are welcome to redistribute it\n" 120 | "under certain conditions; see the LICENSE file for details.\n" 121 | "\n" 122 | "Usage: \n" 123 | " rtl_868 [PARAMETERS] [FILENAME]\n" 124 | " [FILENAME] read input data from there. Defaults to stdin.\n" 125 | " [PARAMETERS] Unix style parameters with possible values:\n" 126 | " -v be more verbose. accumulates when given multiple times.\n" 127 | " -q be less verbose.\n" 128 | " -f file open file instead of stdin.\n" 129 | " -o file open file instead of stdout.\n" 130 | "\n" 131 | ); 132 | return 1; 133 | default: 134 | abort (); 135 | } 136 | 137 | if ((argc - 1 == optind) && (filename == 0)) { 138 | logging_verbose( "Using positional argument '%s' as input filename.\n", argv[optind] ); 139 | // if there is a single remaining argument, use it as filename 140 | filename = argv[optind]; 141 | } else { 142 | int index; 143 | for (index = optind; index < argc; index++) { 144 | logging_error( "Unkown non-option argument %s\n", argv[index] ); 145 | return 1; 146 | } 147 | } 148 | 149 | if (filename == 0) { 150 | filename = "-"; 151 | } 152 | if (outfilename == 0){ 153 | outfilename = "-"; 154 | } 155 | logging_verbose( "decode.c version 0, verbose %i, filename %s -> %s.\n", verbose, filename, outfilename ); 156 | logging_info( 157 | "rtl_868, Copyright (C) 2015 Clemens Helfmeier\n" 158 | "rtl_868 comes with ABSOLUTELY NO WARRANTY; for details see the\n" 159 | "LICENSE file distributed with the program.\n" 160 | "This is free software, and you are welcome to redistribute it\n" 161 | "under certain conditions; see the LICENSE file for details.\n" 162 | ); 163 | 164 | if ((filename == 0) || (strcmp( filename, "-" ) == 0)) 165 | in = stdin; 166 | else 167 | in = fopen( filename, "r" ); 168 | if (in == 0) { 169 | if (filename == 0) { 170 | logging_error( "Could not open stdin as input file.\n" ); 171 | } else { 172 | logging_error( "Could not open input file '%s'.\n", filename ); 173 | } 174 | return 1; 175 | } 176 | 177 | if ((outfilename == 0) || (strcmp( outfilename, "-" ) == 0)) 178 | out = stdout; 179 | else 180 | out = fopen( outfilename, "a" ); 181 | if (out == 0) { 182 | if (outfilename == 0) { 183 | logging_error( "Could not open stdout as output file.\n" ); 184 | } else { 185 | logging_error( "Could not open output file '%s'.\n", outfilename ); 186 | } 187 | return 1; 188 | } 189 | 190 | stream_decoder_t mysd = { .init = 0, .input = &duplicate_stream_input }; 191 | 192 | // construct the signal chain 193 | /* transmission decoder */ 194 | td.init( &nrz ); 195 | /* nrz */ 196 | nrz.init( &mysd ); 197 | /* ws300 and tx29 */ 198 | ws300.init( &dl_file ); 199 | tx29.init( &dl_file ); 200 | /* dl_file */ 201 | dl_file.init( out ); 202 | 203 | uint16_t d[1024]; 204 | unsigned long long int ndata = 0; 205 | unsigned long long int last_ndata = 0; 206 | 207 | struct timespec last_status; 208 | #ifdef __APPLE__ 209 | last_status.tv_sec = time(NULL); 210 | last_status.tv_nsec = 0; 211 | #else 212 | clock_gettime( CLOCK_MONOTONIC, &last_status ); 213 | #endif 214 | 215 | // read from stdin S16LE data 216 | while (1) { 217 | /* read a chunk */ 218 | int n = fread( d, sizeof(d[0]), sizeof(d)/sizeof(d[0]), in ); 219 | if (n == 0) { 220 | logging_error( "\nEOF reached at %i.\n", ndata ); 221 | break; 222 | } else { 223 | ndata += n; 224 | } 225 | 226 | struct timespec now; 227 | #ifdef __APPLE__ 228 | now.tv_sec = time(NULL); 229 | now.tv_nsec = 0; 230 | #else 231 | clock_gettime( CLOCK_MONOTONIC, &now ); 232 | #endif 233 | // if time is over, redisplay status 234 | float dt = 1.0 * (now.tv_sec - last_status.tv_sec) + 1.0 * (now.tv_nsec - last_status.tv_nsec) / 1e9; 235 | if (dt >= 1) { 236 | // calculate new throughput 237 | float throughput = (ndata - last_ndata) / dt; 238 | last_ndata = ndata; 239 | 240 | /* update status display */ 241 | char nd_e; 242 | float nd_b; 243 | data_to_string( (float)ndata, &nd_b, &nd_e ); 244 | char tp_e; 245 | float tp_b; 246 | data_to_string( throughput, &tp_b, &tp_e ); 247 | logging_status( 0, "%s -> %s, %1.1f%c, %1.1f%c", filename, outfilename, nd_b, nd_e, tp_b, tp_e ); 248 | 249 | logging_restatus(); 250 | last_status.tv_sec = now.tv_sec; 251 | last_status.tv_nsec = now.tv_nsec; 252 | } 253 | 254 | /* and put the chunk into the transmission decoder */ 255 | int i; 256 | for (i = 0; i 25 | #include "bit_decoder.h" 26 | #include "stream_decoder.h" 27 | #include "nrz_decode.h" 28 | #include "logging.h" 29 | 30 | /// the minimum number of samples a new level must be 31 | /// present before it is considered stable 32 | #define LEVEL_THRESHOLD 2 33 | 34 | /// maximum number of edges to be able to receive 35 | /// set to number of bits of max. length transmission 36 | /// any subsequent edge will be silently ignored 37 | #define EDGE_TIMES_LEN 256 38 | /// maximum bittime in histogram to consider for bitlen determination 39 | #define HIST_LEN 64 40 | /// averaging of bittimes in histogram 41 | #define HIST_AVG 2 42 | #define DATA_LEN (EDGE_TIMES_LEN/8) 43 | 44 | stream_decoder_t *nrz_next; 45 | unsigned int nrz_ok, nrz_err; 46 | 47 | int nrz_init(stream_decoder_t *next) { 48 | if (next == 0) return -1; 49 | nrz_next = next; 50 | nrz_ok = 0; 51 | nrz_err = 0; 52 | logging_info( "NRZ Decoder initialized.\n" ); 53 | } 54 | 55 | int nrz_input(int transmission[], unsigned int length, int noise, int signal) { 56 | /* decode the bits in transmission (1 per index) using NRZ */ 57 | logging_verbose( "Got new transmission of length %i.\n", length ); 58 | // 59 | // 0) convert bits to debounced edge times 60 | int level_counter = 0; 61 | int edge_time = 0; 62 | unsigned int edge_times[EDGE_TIMES_LEN]; 63 | unsigned int edge_times_i = 0; 64 | int last_level = 0; // always start with level zero 65 | int i; 66 | 67 | for (i = 0; i (signal + noise) >> 1) { 71 | level_counter++; 72 | } else if (transmission[i] < -(signal + noise) >> 1) { 73 | level_counter--; 74 | } 75 | if (level_counter < 0) level_counter = 0; 76 | if (level_counter > LEVEL_THRESHOLD) level_counter = LEVEL_THRESHOLD; 77 | if (((last_level == 0) && (level_counter == LEVEL_THRESHOLD)) || ((last_level == 1) && (level_counter == 0))) { 78 | // level has changed 79 | last_level = 1 - last_level; 80 | if (edge_times_i >= EDGE_TIMES_LEN) edge_times_i = EDGE_TIMES_LEN - 1; 81 | edge_times[edge_times_i++] = edge_time; 82 | edge_time = 0; 83 | } 84 | } 85 | // the end of transmission is also an edge 86 | if (edge_times_i >= EDGE_TIMES_LEN) edge_times_i = EDGE_TIMES_LEN - 1; 87 | edge_times[edge_times_i++] = edge_time; 88 | logging_verbose( "Tranmission contains %i edges.\n", edge_times_i ); 89 | /// 1) convert the edge times to histogram 90 | unsigned int hist[HIST_LEN]; 91 | for (i = 0; i 0) && (edge_times[i] < HIST_LEN)) 97 | hist[edge_times[i]]++; 98 | } 99 | _logging_verbose( "\n" ); 100 | /// find the maximum of the histogram as bittime 101 | unsigned int hist_max = 0; 102 | unsigned int hist_max_i = 0; 103 | logging_verbose( "Histogram is: " ); 104 | for (i = 1; i hist_max) { 107 | hist_max = hist[i]; 108 | hist_max_i = i; 109 | } 110 | } 111 | _logging_verbose( "\n" ); 112 | if (hist_max_i == 0) { 113 | logging_warning( "Found no histogram max index.\n" ); 114 | return -2; 115 | } else { 116 | logging_verbose( "Histogram max is at %i.\n", hist_max_i ); 117 | } 118 | /// and calculate the bittime from multiple histogram entries 119 | unsigned int multbitlen; 120 | unsigned int multbitnum; 121 | multbitlen = hist[hist_max_i] * hist_max_i; 122 | multbitnum = hist[hist_max_i]; 123 | for (i = 1; i < HIST_AVG; i++){ 124 | if ((hist_max_i + i < HIST_LEN) && (hist_max_i - i > 0)) { 125 | multbitlen += 126 | hist[hist_max_i-i] * (hist_max_i - i) + 127 | hist[hist_max_i+i] * (hist_max_i + i); 128 | multbitnum += 129 | hist[hist_max_i-i] + 130 | hist[hist_max_i+i]; 131 | } 132 | } 133 | float bitlen = 1.0 * multbitlen / multbitnum; 134 | logging_info( "Tranmission bit length is %1.2f.\n", bitlen ); 135 | /// 2) convert the edges to bits using bitlen 136 | /* now decode the data */ 137 | int data[DATA_LEN]; 138 | data[0] = 0; 139 | unsigned int datai = 0; 140 | unsigned int datab = 0; 141 | int level = 0; 142 | float t = 0; 143 | for (i = 1 + (transmission[1] == 1 ? 1 : 0); i < edge_times_i; i++ ) { 144 | level = 1 - level; 145 | if (edge_times[i] > 32*bitlen) { 146 | continue; 147 | } 148 | t = edge_times[i]; 149 | for (;t > bitlen / 2; t -= bitlen) { 150 | data[datai] <<= 1; 151 | data[datai] |= level; 152 | datab++; 153 | if (datab >= 8) { 154 | datab = 0; 155 | datai++; 156 | if (datai >= DATA_LEN) { 157 | logging_error( "No more memory.\n" ); 158 | datai = DATA_LEN - 1; 159 | } 160 | data[datai] = 0; 161 | } 162 | } 163 | if (abs(t) > bitlen / 5) 164 | logging_info( "Remainder of time is large at bit %i: %1.3f samples at %1.3f bitlen.\n", datai * 8 + datab, t, bitlen ); 165 | } 166 | // shift the last byte so that the first bit starts at MSB 167 | if (datab != 0) { 168 | for (i = datab;(i & 7) != 0; i++) { 169 | data[datai] <<= 1; 170 | } 171 | datai++; 172 | } 173 | logging_info( "Transmission has %i bits packed in %i bytes: ", datab + (datai-1)*8, datai ); 174 | for (i = 0; iinput( data, datai ) == 0) 179 | nrz_ok++; 180 | else 181 | nrz_err++; 182 | // update status 183 | logging_status( 2, "bl=%1.2fS/b tl=%ib nerr=%i nok=%i", bitlen, datab + (datai-1)*8, nrz_err, nrz_ok ); 184 | return 0; 185 | } 186 | 187 | bit_decoder_t nrz = { 188 | .name = "Non-Return-to-Zero decoder for bipolar signals", 189 | .shorthand = "nrz", 190 | .init = nrz_init, 191 | .input = nrz_input 192 | }; 193 | 194 | 195 | -------------------------------------------------------------------------------- /nrz_decode.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | 23 | #ifndef NRZ_DECODE_H 24 | #define NRZ_DECODE_H 1 25 | 26 | #include "bit_decoder.h" 27 | extern bit_decoder_t nrz; 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /sample_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #ifndef SAMPLE_DECODER_H 23 | #define SAMPLE_DECODER_H 1 24 | 25 | #include "bit_decoder.h" 26 | #include 27 | 28 | /* interface for sample decoder */ 29 | typedef struct { 30 | char *name; 31 | char *shorthand; 32 | // interface 33 | int (*init)(bit_decoder_t *next); 34 | int (*input)(int16_t sample); 35 | } sample_decoder_t; 36 | 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /stream_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #ifndef STREAM_DECODER_H 23 | #define STREAM_DECODER_H 1 24 | 25 | #include "data_logger.h" 26 | 27 | /* interface for stream decoder */ 28 | typedef struct { 29 | char *name; 30 | char *shorthand; 31 | // interface 32 | int (*init)(data_logger_t *next); 33 | int (*input)(int transmission[], unsigned length); 34 | } stream_decoder_t; 35 | 36 | 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /temp-daemon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # rtl_868 5 | # Copyright (C) 2015 Clemens Helfmeier 6 | # e-mail: clemenshelfmeier@gmx.de 7 | # 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License along 19 | # with this program; if not, write to the Free Software Foundation, Inc., 20 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 | 22 | 23 | # temperature daemon. 24 | # 25 | # Send SIGUSR1 to this process to force a restart of the 26 | # receiver and decoder and to select the next output filename 27 | # 28 | # output file is named w.r.t. current time. 29 | # 30 | 31 | 32 | # trap the SIGUSR1: 33 | function hnd_SIGUSR1() { 34 | echo "Killing receiver on user request." 35 | kill $RX_PID 36 | wait $RX_PID 37 | } 38 | trap hnd_SIGUSR1 SIGUSR1 39 | 40 | cd `dirname $0` 41 | 42 | while true; do 43 | # determine output filename 44 | FN="temp-`date +%Y%m%d-%H%M.csv`" 45 | echo "Using output filename \"${FN}\"." 46 | # start the daemon in background 47 | rtl_fm -f 868.26e6 -M fm -s 500k -r 75k -g 42 -A fast | ./rtl_868 -vvv >>${FN} & 48 | RX_PID=$! 49 | # wait for signal or termination 50 | wait ${RX_PID} 51 | ERET=$? 52 | if (( $ERET <= 128 )); then 53 | echo "" 54 | echo "Process exited with $ERET."; 55 | break; 56 | fi 57 | echo "Done. Will restart receiver on next loop." 58 | done; 59 | 60 | -------------------------------------------------------------------------------- /tools.c: -------------------------------------------------------------------------------- 1 | 2 | /** From Chromium Repository, crc8.c, adapted to allow varying polynoms by Clemens Helfmeier */ 3 | // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | #include 32 | #include "logging.h" 33 | 34 | uint8_t crc8(uint16_t poly, uint8_t *vptr, int len) 35 | { 36 | const uint8_t *data = vptr; 37 | uint16_t crc = 0; 38 | int i, j; 39 | for (j = len; j; j--, data++) { 40 | crc ^= (*data << 8); 41 | for(i = 8; i; i--) { 42 | if (crc & 0x8000) 43 | crc ^= (poly << 7); 44 | crc <<= 1; 45 | } 46 | } 47 | return (uint8_t)(crc >> 8); 48 | } 49 | 50 | int search_magic(int transmission[], unsigned length, uint8_t tm[], int tm_length, int magic[], int magic_length) { 51 | /* search for magic_lenght bits (given by magic[]) within transmission[] and return the 52 | * properly shifted version of transmission[] in tm[], so that 53 | * tm[0] is magic[0], etc. 54 | * tm_length must be larger than magic_length! 55 | * return number of bytes within tm. 56 | */ 57 | unsigned int shift; 58 | unsigned int ofs; 59 | unsigned int shf; 60 | int inv = 0; 61 | unsigned int i = 0; 62 | for (shift = 0; shift < length*8; shift++) { 63 | ofs = shift >> 3; 64 | shf = shift & 7; 65 | // check if we would already exceed packet size with preamble and length field 66 | if (magic_length + (shift + 7) >> 3 > length) { 67 | logging_warning( "Transmission too short: %i.\n", length ); 68 | return 0; 69 | } 70 | for (i = 0; i <= (magic_length | 0x07) >> 3; i++) { 71 | tm[i] = ((transmission[i+ofs+1] | (transmission[i+ofs]<<8)) >> (8-shf)) & 0xFF; 72 | } 73 | // now check tm 74 | int found = 0; 75 | int msk; 76 | for (i = 0; i < (magic_length | 0x07) >> 3; i++) { 77 | if (i << 3 > magic_length) { 78 | msk = (1<<(magic_length & 0x07)) - 1; 79 | } else { 80 | msk = 0xFF; 81 | } 82 | if ((tm[i] & msk) != (magic[i] & msk)) 83 | found |= 1; 84 | if (((tm[i] & msk) ^ 0xFF) != (magic[i] & msk)) 85 | found |= 2; 86 | if (found == 0x03) { 87 | break; 88 | } 89 | } 90 | // bit in found is set if at least one of the 91 | // magic bytes did not match 92 | if (found == 0x01) { 93 | inv = 0xFF; 94 | break; 95 | } 96 | if (found == 0x02) { 97 | inv = 0x00; 98 | break; 99 | } 100 | } 101 | if (shift >= length*8) { 102 | logging_warning( "No preamble detected. Ignoring dataset.\n" ); 103 | return 0; 104 | } 105 | // fill the shifted data into tm and empty bits with 0 106 | for (i = 0; (i> (8-shf)) & 0xFF; 109 | } else if (i+ofs < length) { 110 | tm[i] = (((transmission[i+ofs]<<8)) >> (8-shf)) & 0xFF; 111 | } else { 112 | tm[i] = 0; 113 | } 114 | tm[i] ^= inv; 115 | } 116 | ofs = length - ofs; // number of filled bytes in tm 117 | if (ofs >= tm_length/sizeof(tm[0])) { 118 | ofs = tm_length/sizeof(tm[0]); 119 | } 120 | return ofs; 121 | } 122 | -------------------------------------------------------------------------------- /tools.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #ifndef TOOLS_H 23 | #define TOOLS_H 1 24 | 25 | #include 26 | 27 | /** calculate crc8 */ 28 | uint8_t crc8( uint16_t poly, uint8_t *data, int len ); 29 | int search_magic(int transmission[], unsigned length, uint8_t tm[], int tm_length, int magic[], int magic_length); 30 | 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /transmission.c: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include "sample_decoder.h" 26 | #include "transmission.h" 27 | #include "logging.h" 28 | 29 | /// maximum number of samples within one transmission, 30 | /// everything exceeding this will be silently dropped 31 | #define TD_SAMPLES_LEN 1024 32 | 33 | 34 | typedef int16_t td_sample_t; 35 | typedef int32_t td_sample2x_t; 36 | 37 | /* where to handle received samples to */ 38 | bit_decoder_t *td_next; 39 | int td_samples[TD_SAMPLES_LEN]; 40 | unsigned int td_samples_i; 41 | 42 | /// threshold: this many samples required into either 43 | /// direction to detect a transmission 44 | #define TRANSMISSION_THRESHOLD 10 45 | /// this much must the amplitude exceed the mean amplitude 46 | /// for digital value detection 47 | #define SAMPLE_AMPLITUDE_FACTOR 2 48 | /// this many samples are kept before the transmission starts 49 | /// according to the TRANSMISSION_THRESHOLD and after 50 | /// it has ended 51 | #define SAMPLE_RESERVOIR 32 52 | 53 | td_sample2x_t td_mean = 500<<(sizeof(td_sample_t)*8); 54 | int td_transtime; 55 | td_sample2x_t td_sigpwr; 56 | int td_fade; 57 | 58 | int td_init( bit_decoder_t *next ) { 59 | if (next == 0) return -1; 60 | td_next = next; 61 | td_samples_i = 0; 62 | td_fade = 0; 63 | logging_info( "Transmission decoder initialized.\n" ); 64 | } 65 | 66 | int td_input( td_sample_t sample ) { 67 | // memorize the amplitude 68 | td_sample_t sample_amplitude = td_mean >> (sizeof(td_sample_t)*8); 69 | td_mean += abs(sample) - (sample_amplitude); 70 | // check for transmission 71 | int new_transtime = td_transtime; 72 | if ((sample > SAMPLE_AMPLITUDE_FACTOR * sample_amplitude) || (sample < - SAMPLE_AMPLITUDE_FACTOR * sample_amplitude)) { 73 | new_transtime++; 74 | } else { 75 | new_transtime--; 76 | } 77 | if (new_transtime > 2*TRANSMISSION_THRESHOLD) { 78 | new_transtime = 2*TRANSMISSION_THRESHOLD; 79 | } else if (new_transtime < 0) { 80 | new_transtime = 0; 81 | } 82 | // memorize the new sample 83 | td_samples[td_samples_i++] = sample; 84 | if (td_samples_i >= TD_SAMPLES_LEN) td_samples_i = TD_SAMPLES_LEN - 1; 85 | // see if we have no transmission 86 | if ((new_transtime < TRANSMISSION_THRESHOLD) && (td_fade == 0)) { 87 | // signal is weak and no transmission is running 88 | if (td_samples_i >= SAMPLE_RESERVOIR) { 89 | // only keep SAMPLE_RESERVOIR samples 90 | memmove( &td_samples[0], &td_samples[td_samples_i - SAMPLE_RESERVOIR + 1], (SAMPLE_RESERVOIR - 1) * sizeof(td_samples[0]) ); 91 | td_samples_i = SAMPLE_RESERVOIR - 1; 92 | } 93 | } else { 94 | // either signal is strong or we had a transmission running 95 | if (new_transtime >= TRANSMISSION_THRESHOLD) { 96 | // signal is strong, so transmission is technically still running 97 | if (td_fade == 0) { 98 | // start of transmission 99 | logging_verbose( "Start of transmission found.\n" ); 100 | td_sigpwr = 0; 101 | } else { 102 | // simply within a transmission 103 | } 104 | td_fade = SAMPLE_RESERVOIR; 105 | // memorize the signal amplitude 106 | td_sigpwr += abs(sample); 107 | } else { 108 | // signal is weak so transmission is over 109 | td_fade--; 110 | if (td_fade == 0) { 111 | if ((float)td_sigpwr/(float)td_samples_i > td_mean >> (sizeof(td_sample_t)*8)) { 112 | // last sample of transmission is recorded 113 | if (td_samples_i < 3 * TRANSMISSION_THRESHOLD) { 114 | logging_verbose( "Dropping transmission, too short: %i samples, noise floor=%i, signal=%1.0f.\n", td_samples_i, (td_mean>>(sizeof(td_sample_t)*8)), (float)td_sigpwr/(float)td_samples_i ); 115 | } else { 116 | logging_info( "Got Transmission of %i samples, noise floor=%i, signal=%1.0f.\n", td_samples_i, (td_mean>>(sizeof(td_sample_t)*8)), (float)td_sigpwr/(float)td_samples_i ); 117 | logging_status( 1, "n=%i, s=%1.0f, l=%i", (td_mean>>(sizeof(td_sample_t)*8)), (float)td_sigpwr/(float)td_samples_i, td_samples_i ); 118 | td_next->input( td_samples, td_samples_i, (td_mean>>(sizeof(td_sample_t)*8)), (int)((float)td_sigpwr/(float)td_samples_i) ); 119 | } 120 | } else { 121 | logging_verbose( "Transmission too weak: signal %1.0f, noise floor=%i.\n", (float)td_sigpwr/(float)td_samples_i, td_mean >> (sizeof(td_sample_t)*8) ); 122 | } 123 | } else { 124 | // still recording samples but transmission is already over. 125 | } 126 | } 127 | } 128 | td_transtime = new_transtime; 129 | } 130 | 131 | sample_decoder_t td = { 132 | .name = "Transmission decoder for bipolar signals (e.g. FM).", 133 | .shorthand = "td", 134 | .init = td_init, 135 | .input = td_input 136 | }; 137 | -------------------------------------------------------------------------------- /transmission.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef TRANSMISSION_H 22 | #define TRANSMISSION_H 1 23 | 24 | #include "sample_decoder.h" 25 | extern sample_decoder_t td; 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tx29.c: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | // this is some other code, very similar to what is known as TX29 22 | // on the internet. 23 | 24 | #include "stream_decoder.h" 25 | #include "logging.h" 26 | #include "tools.h" 27 | #include "data_logger.h" 28 | 29 | data_logger_t *tx29_next; 30 | 31 | int tx29_init( data_logger_t *next ) { 32 | if (next == 0) return -1; 33 | tx29_next = next; 34 | logging_info( "TX29 decoder initialized.\n" ); 35 | } 36 | 37 | int tx29_input(int transmission[], unsigned length) { 38 | // find preamble it is 2d d4 and stuff before must be aa 39 | unsigned int ofs; 40 | int i; 41 | int magic[] = {0xaa, 0x2d, 0xd4}; 42 | uint8_t tm[11]; 43 | // find magic 44 | ofs = search_magic( transmission, length, tm, sizeof(tm)/sizeof(tm[0]), magic, 8*sizeof(magic)/sizeof(magic[0]) ); 45 | if (ofs == 0) { 46 | return -1; 47 | } 48 | // 49 | logging_info( "Data packet after preamble detection: %i -> ", ofs ); 50 | for (i = 0; (i>4) & 0x0F; 56 | len = (len + 1) >> 1; // convert to bytes 57 | if (len > ofs - 4) { 58 | logging_warning( "Invalid length field %i. Ignoring dataset.\n", len ); 59 | return -4; 60 | } 61 | // check the checksum 62 | uint8_t crc = crc8(0x131, &tm[3], len); 63 | if (crc != 0) { 64 | logging_warning( "Invalid checksum %02x detected. Ignoring dataset.\n", crc ); 65 | return -6; 66 | } 67 | int sensid; 68 | int newbatt; 69 | float temp; 70 | float rel_hum; 71 | int weakbatt; 72 | if (len == 5) { 73 | // the tm is correct 74 | sensid = ((tm[3] & 0x0f) << 2) | ((tm[4]>>6) & 0x03); 75 | newbatt = (tm[4] >> 5) & 1; 76 | temp = 10.0 * (tm[4] & 0x0F) + 1.0 *((tm[5]>>4) & 0x0F) + 0.1 * (tm[5] & 0x0F) - 40.0; 77 | weakbatt = (tm[6]>>7) & 1; 78 | rel_hum = 1.0 * (tm[6] & 0x7F); 79 | } else { 80 | logging_warning( "Don't know how to handle data of length %i.\n", len ); 81 | return -5; 82 | } 83 | logging_info( "Recieved dataset: sensid=%i, newbatt=%i, weakbatt=%i, temp=%1.1f°C, rel_hum=%1.0f%%.\n", sensid, newbatt, weakbatt, temp, rel_hum ); 84 | return tx29_next->input( sensid, temp, rel_hum, newbatt | (weakbatt << 1) ); 85 | } 86 | 87 | 88 | stream_decoder_t tx29 = { 89 | .name = "Decoder for TX29 weather stations.", 90 | .shorthand = "tx29", 91 | .init = tx29_init, 92 | .input = tx29_input 93 | }; 94 | 95 | 96 | -------------------------------------------------------------------------------- /tx29.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef TX29_H 22 | #define TX29_H 1 23 | 24 | extern stream_decoder_t tx29; 25 | 26 | 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ws300.c: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | // This type of data is received for example for ALDI type weather stations 22 | // the devices at hand have a bug, after 23.7°C, the next (upwards) step is 23.0°C 23 | 24 | #include "stream_decoder.h" 25 | #include "logging.h" 26 | #include "data_logger.h" 27 | #include "tools.h" 28 | 29 | data_logger_t *ws300_next; 30 | 31 | 32 | int ws300_init( data_logger_t *next ) { 33 | if (next == 0) return -1; 34 | ws300_next = next; 35 | logging_info( "WS300 decoder initialized.\n" ); 36 | } 37 | 38 | int ws300_input(int transmission[], unsigned length) { 39 | /* decoding the result: 40 | * aa aa 2d d4 51 11 4d 07 29 21 00 41 | * ^^ checksumme 42 | * ^^ rel. hum 0x29 = 41% 43 | * ^^ ^^ Temperatur in Vorkomma & Nachkomma in °C bezogen auf -50°C 44 | * 0x4d07 = -50°C + 77°C + 0.7°C = 27.7°C 45 | * ^ Hauscode: 1...15 = 1...f 46 | * ^ Kanal: 1...3 = 1...3, 4 = 0 47 | * ^^^^^ preamble 48 | * 49 | */ 50 | int ofs; 51 | int i; 52 | int magic[] = {0xaa, 0x2d, 0xd4}; 53 | uint8_t tm[11]; 54 | // find magic 55 | ofs = search_magic( transmission, length, tm, sizeof(tm)/sizeof(tm[0]), magic, 8*sizeof(magic)/sizeof(magic[0]) ); 56 | if (ofs < 8) { 57 | logging_warning( "Transmission too short: %i.\n", ofs ); 58 | return -2; 59 | } 60 | // check the preamble 61 | if (!(tm[3] == 0x51)) { 62 | logging_warning( "Invalid preamble field %02x detected. Ignoring dataset.\n", tm[3] ); 63 | return -3; 64 | } 65 | // check the checksum 66 | int crc = (tm[3] + tm[4] + tm[5] + tm[6] + tm[7] + tm[8]) & 0xFF; 67 | if (crc != 0) { 68 | logging_warning( "Invalid checksum %02x detected. Ignoring dataset.\n", crc ); 69 | return -4; 70 | } 71 | // the transmissionset is correct 72 | int hauscode = tm[4] & 0x0F; 73 | int channel = ((tm[4]>>4) & 0x3); 74 | if (channel == 0) channel = 4; 75 | float rel_hum = 1.0 * tm[7]; 76 | float temp = 1.0 * tm[5] + 0.1 * tm[6] - 50.0; 77 | logging_info( "Recieved dataset: hauscode=%i, channel=%i, temp=%1.1f°C, rel_hum=%1.0f%%.\n", hauscode, channel, temp, rel_hum ); 78 | return ws300_next->input( (hauscode<<8) | channel, temp, rel_hum, 0 ); 79 | } 80 | 81 | 82 | stream_decoder_t ws300 = { 83 | .name = "Decoder for WS-300 weather stations.", 84 | .shorthand = "ws300", 85 | .init = ws300_init, 86 | .input = ws300_input 87 | }; 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /ws300.h: -------------------------------------------------------------------------------- 1 | /* 2 | rtl_868 3 | Copyright (C) 2015 Clemens Helfmeier 4 | e-mail: clemenshelfmeier@gmx.de 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License along 17 | with this program; if not, write to the Free Software Foundation, Inc., 18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef WS300_H 22 | #define WS300_H 1 23 | 24 | extern stream_decoder_t ws300; 25 | 26 | 27 | 28 | 29 | #endif 30 | --------------------------------------------------------------------------------