commit 0a28bac78a135e814a79bf749cd264d1919962a0 Author: Steffen Lange Date: Sun Apr 8 21:34:42 2018 +0200 First commit diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..e471128 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,29 @@ +############# +# CHANGELOG # +############# + +Version 0.2.3 (2016-02-28) +========================= ++ Added manpage +* Renamed some files +- No binary stripping + +Version 0.2.2 (2015-04-25) +========================== +* Revised init scripts + +Version 0.2.1 (2015-03-01) +========================== ++ Added packaging scripts for Debian and OpenWrt + +Version 0.2 (2015-02-22) +======================== ++ Added simple Geiger simulator ++ Added support for Safecast API +- Disabled IPv6 +* Fixed timezone problem +* Minor bug fixes + +Version 0.1 (2015-02-01) +======================== +* First public release diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6b3dfef --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +OBJECTS = trim.o map.o logger.o ini.o tcpcli.o diygeiger.o gqgeiger.o gclog.o +CFLAGS += -Wall -Wextra -Os +#LDFLAGS += +PREFIX ?= /usr + +all: gclog + +gclog: $(OBJECTS) + $(CC) $(LDFLAGS) -o $@ $(OBJECTS) + which upx >/dev/null 2>&1 && upx -9 -qq $@ || true + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +install: all + install -d $(DESTDIR)$(PREFIX)/bin + install -d $(DESTDIR)/etc + install -d $(DESTDIR)/etc/init.d + install -d $(DESTDIR)$(PREFIX)/share/man/man1 + install -m 755 gclog $(DESTDIR)$(PREFIX)/bin/ + install -m 600 gclog.conf $(DESTDIR)/etc/ + install -m 755 gclogd $(DESTDIR)/etc/init.d/ + install -m 644 gclog.1 $(DESTDIR)$(PREFIX)/share/man/man1/ + +clean: + -rm $(OBJECTS) 2>/dev/null diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..9c01f42 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,21 @@ +# Maintainer: Steffen Lange +pkgname=gclog +pkgver=0.2.3 +pkgrel=1 +pkgdesc="Geiger Counter Logger" +arch=('i686' 'x86_64') +url="http://www.dateihal.de/cms/gclog" +license=('GPL3') +depends=('sh') +source=("http://www.dateihal.de/${pkgname}/${pkgname}-${pkgver}.tar.gz") +md5sums=('SKIP') + +build() { + cd "$srcdir/$pkgname-$pkgver" + make +} + +package() { + cd "$srcdir/$pkgname-$pkgver" + make DESTDIR="$pkgdir/" install +} diff --git a/README b/README new file mode 100644 index 0000000..079b76e --- /dev/null +++ b/README @@ -0,0 +1,43 @@ + ___ Geiger Counter LOGger + \_/ Version 0.2.3 +.--,O.--, + \/ \/ Copyright (C) 2014-16 Steffen Lange, gclog@stelas.de + +This program comes with ABSOLUTELY NO WARRANTY. +This is free software, and you are welcome to redistribute it +under certain conditions. See the file COPYING for details. + +GCLOG is a lightweight daemon running in the background and +constantly reporting your Geiger counter readings to various +radiation monitoring websites. With a small footprint and +minimal dependencies it is aimed to run on Linux embedded +computers, like Raspberry Pi or TP-Link WR703N. + +Supported Geiger counter devices: +- GQ Electronics GMC-280, GMC-300, GMC-300E, GMC-300E Plus, GMC-320 and + GMC-320 Plus + http://www.gqelectronicsllc.com/comersus/store/LeftStart.asp?idCategory=50 +- DIY Geiger Kit GK-B5 and GK-Plus + https://sites.google.com/site/diygeigercounter/ +- RH Electronics MyGeiger, MyGeiger 2, Universal SMT Kit and Arduino IDE Kit + http://www.rhelectronics.net/store/diy-geiger-counter-kit.html +- NET-IO Devices GC08 and GC10 + http://www.netiodev.com/ +- Arduino Geiger PCB + http://arduino-geiger-pcb.blogspot.de/ + +Supported radiation monitoring websites: +- radmon.org +- Safecast.org +- NETC.com +Please read the terms of service before using these websites. + +Installation +------------ +1. Download, untar and make +2. Copy daemon executable to /usr/local/bin/gclog + and configuration file to /etc/gclog.conf +3. Modify configuration to your needs +4. Start GCLOG: gclog -d -c /etc/gclog.conf +5. Monitor syslog +6. Stop GCLOG: killall gclog diff --git a/README.Packaging b/README.Packaging new file mode 100644 index 0000000..e9c92a1 --- /dev/null +++ b/README.Packaging @@ -0,0 +1,29 @@ +Packaging Geiger Counter Logger +=============================== + +OpenWrt +------- +Recipe from: https://wiki.openwrt.org/doc/howto/obtain.firmware.sdk + +1. Download precompiled SDK (.tar.bz2 archive) +2. Copy openwrt/Makefile to /package/gclog/ +3. make package/gclog/download +4. make package/gclog/compile +5. IPK package is created in /bin directory + +Debian +------ +Recipe from: https://wiki.debian.org/IntroDebianPackaging + +1. apt-get install build-essential debhelper devscripts +2. Rename gclog-.tar.gz to gclog_.orig.tar.gz +3. Untar source archive +4. debuild -us -uc +5. DEB package is created in parent directory + +RPM-based distro +---------------- +1. Install gcc, make and rpm-build +2. Copy gclog-.tar.gz to ~/rpmbuild/SOURCES/ +3. rpmbuild -ba gclog.spec +4. RPM package is created in ~/rpmbuild/RPMS directory diff --git a/TODO b/TODO new file mode 100644 index 0000000..7ba84a2 --- /dev/null +++ b/TODO @@ -0,0 +1,10 @@ +######## +# TODO # +######## + +* Implement better logging and debug mode +* Multithreading: run I/O operations in separate threads +* HTTPS: add SSL support to TCP client +* Support for Radioactive@Home (BOINC platform) +* Plugins: interfaces for radiation monitoring websites + and Geiger counter communication protocols diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..f938962 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,17 @@ +gclog (0.2.3-1) unstable; urgency=low + + * Minor fixes + + -- Steffen Lange Sun, 28 Feb 2016 12:00:00 +0100 + +gclog (0.2.2-1) unstable; urgency=low + + * New upstream release + + -- Steffen Lange Sat, 25 Apr 2015 12:00:00 +0200 + +gclog (0.2.1-1) unstable; urgency=low + + * Initial package of version 0.2.1 + + -- Steffen Lange Sat, 28 Feb 2015 12:00:00 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..0f3afd3 --- /dev/null +++ b/debian/control @@ -0,0 +1,15 @@ +Source: gclog +Section: misc +Priority: optional +Maintainer: Steffen Lange +Build-Depends: debhelper (>= 9) +Standards-Version: 3.9.7 +Homepage: http://www.dateihal.de/cms/gclog + +Package: gclog +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Geiger Counter Logger + GCLOG is a lightweight daemon running in the background and + constantly reporting your Geiger counter readings to various + radiation monitoring websites. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..f6419c0 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,4 @@ +Copyright (C) 2014-16 Steffen Lange + +This is free software, licensed under the GNU General Public License v3. +See /usr/share/common-licenses/GPL-3 for more information. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..63726a4 --- /dev/null +++ b/debian/docs @@ -0,0 +1,3 @@ +README +README.Packaging +TODO diff --git a/debian/gclog.manpages b/debian/gclog.manpages new file mode 100644 index 0000000..b0ce21e --- /dev/null +++ b/debian/gclog.manpages @@ -0,0 +1 @@ +gclog.1 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..40fdf50 --- /dev/null +++ b/debian/rules @@ -0,0 +1,10 @@ +#!/usr/bin/make -f + +export DEB_BUILD_HARDENING=1 + +%: + dh $@ + +# quick file permission fix +override_dh_fixperms: + dh_fixperms -Xetc/gclog.conf diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/diygeiger.c b/diygeiger.c new file mode 100644 index 0000000..c5f71c0 --- /dev/null +++ b/diygeiger.c @@ -0,0 +1,52 @@ +#include "diygeiger.h" + +int diy_open(const char *device) { + int fd = -1; + struct termios tio; + + memset(&tio, 0, sizeof(struct termios)); + tio.c_cflag = CS8 | CREAD | CLOCAL; // 8n1 + tio.c_cc[VMIN] = 0; + tio.c_cc[VTIME] = 5; + + if ((fd = open(device, O_RDWR)) != -1) { + if (cfsetspeed(&tio, B9600) == 0) // 9600 baud + if (tcsetattr(fd, TCSANOW, &tio) == 0) + // Return file descriptor, + return fd; + + // ... otherwise close device. + close(fd); + fd = -1; + } + + return fd; +} + +void diy_close(int device) { + close(device); +} + +int diy_get_cpm(int device) { + char buf[13] = { 0 }; + + // Arduino sends 10-digit decimal number (unsigned long) plus tailing "\r\n". + diy_read(device, buf, 12); + + return atoi(buf); +} + +int diy_read(int device, char *buf, unsigned int len) { + unsigned int n; + ssize_t rcvd = 0; + char *inp = &buf[0]; + + for (n = 0; n < len; n++) { + rcvd += read(device, inp, 1); + inp = &buf[rcvd]; + if (rcvd >= len) + break; + } + + return rcvd; +} diff --git a/diygeiger.h b/diygeiger.h new file mode 100644 index 0000000..8aaf91e --- /dev/null +++ b/diygeiger.h @@ -0,0 +1,20 @@ +#ifndef _DIYGEIGER_H_ +#define _DIYGEIGER_H_ + +#include +#include +#include +#include +#include +#include + +/* + Specification of GC10 Data I/O Interface: http://netiodev.com/GC10/GC10_UART_SPEC.pdf +*/ + +int diy_open(const char *device); +void diy_close(int device); +int diy_get_cpm(int device); +int diy_read(int device, char *buf, unsigned int len); + +#endif diff --git a/gclog.1 b/gclog.1 new file mode 100644 index 0000000..c5df28d --- /dev/null +++ b/gclog.1 @@ -0,0 +1,87 @@ +.TH GCLOG 1 "February 2016" "GCLOG 0.2" "Geiger Counter Logger" + +.SH NAME +.B gclog +\- Geiger Counter Logger Daemon + +.SH SYNOPSIS +.B gclog +.RB [ \-c +.IR file ] +.RB [ \-d ] + +.SH DESCRIPTION +\fBGCLOG\fP is a lightweight daemon running in the background and constantly reporting your Geiger counter readings to various radiation monitoring websites. With a small footprint and minimal dependencies it is aimed to run on Linux embedded computers. + +.SH OPTIONS +.TP +.B -c \fIfile\fP +Load configuration from file. + +.TP +.B -d +Activate verbose mode. + +.SH CONFIGURATION FILE OPTIONS +.TP +.B device.type +Geiger counter type: + +\fBgq\fP - GQ GMC Geiger Counter (GQ-RFC1201 protocol) + +\fBdiy\fP - DIY/MyGeiger/NET-IO Geiger Kit or compatible + +\fBsim\fP - Geiger simulator (reads 12 cpm) + +.TP +.B device.port +Serial device filename. + +Example: \fI/dev/ttyUSB0\fP + +.TP +.B location +Name of your sensor location (required for Safecast). + +Example: Berlin, DE + +.TP +.B latitude +Latitude of your sensor position (required for Safecast). + +Example: 52.5163 + +.TP +.B longitude +Longitude of your sensor position (required for Safecast). + +Example: 13.3777 + +.TP +.B interval +Polling interval in seconds. + +Range: 60..3600 + +.TP +.B radmon.user +Your forum username (required for radmon). + +.TP +.B radmon.pass +Your password received via PM from `mw0uzo' (required for radmon). + +.TP +.B safecast.key +Your API key is listed on your profile page (required for Safecast). + +.TP +.B safecast.device +Find your device ID on the Safecast list (required for Safecast). + +.TP +.B netc.id +First use their `\fIwapp4netc.exe\fP' software to register your Geiger counter ID (required for Nuclear Emergency Tracking Center). + +.SH AUTHOR +Steffen Lange (gclog@stelas.de) diff --git a/gclog.c b/gclog.c new file mode 100644 index 0000000..58271dd --- /dev/null +++ b/gclog.c @@ -0,0 +1,325 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include "logger.h" +#include "ini.h" +#include "diygeiger.h" +#include "gqgeiger.h" +#include "tcpcli.h" + +#define GCLOG_VERSION "0.2.3" +#define GCLOG_BUILD "2016-02-28" +#define BUF_SIZE 1000 +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +enum EGeiger { SIM, DIY, GQ }; +static const char *GeigerNames[] = { "Geiger simulator", "DIY/MyGeiger/NET-IO Geiger Kit", "GQ GMC Geiger Counter" }; +static volatile bool Running = true; + +int div_round_closest(int n, int d) { + return (n < 0) ^ (d < 0) ? (n - d/2) / d : (n + d/2) / d; +} + +char * string_copy(const char *src) { + char *dst = calloc(strlen(src) + 1, sizeof(char)); + strcpy(dst, src); + + return dst; +} + +bool string_isset(char *str) { + return str != NULL && strlen(str) > 0; +} + +void try_free(char *buf) { + if (buf != NULL) + free(buf); +} + +void signal_handler(int sig) { + switch (sig) { + case SIGTERM: + case SIGINT: + case SIGQUIT: + case SIGHUP: + Running = false; + default: + break; + } +} + +int geiger_open(enum EGeiger type, const char *device) { + int fd = -1; + time_t t = time(NULL); + struct tm *tm = gmtime(&t); + + if (type == GQ) { + if ((fd = gq_open(device)) != -1) { + gq_set_date(fd, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); + gq_set_time(fd, tm->tm_hour, tm->tm_min, tm->tm_sec); + } + } + else if (type == DIY) { + fd = diy_open(device); + } + else if (type == SIM) { + fd = STDIN_FILENO; + } + + return fd; +} + +void geiger_close(enum EGeiger type, int device) { + if (type == GQ) + gq_close(device); + else if (type == DIY) + diy_close(device); +} + +int geiger_get_cpm(enum EGeiger type, int device) { + if (type == GQ) + return gq_get_cpm(device); + else if (type == DIY) + return diy_get_cpm(device); + else if (type == SIM) + return 12; // Guaranteed to be random. :-) + + return 0; +} + +bool send_netc(const char *id, int cpm) { + char *req; + int sock; + char buf[BUF_SIZE] = { 0 }; + + asprintf(&req, "GET /push.php?id=%s&v=w32_1.1.3.1085&c=%d HTTP/1.1\r\nHost: radiation.netc.com\r\n\r\n", id, cpm); + + if ((sock = tcp_connect("radiation.netc.com", "80")) != -1) { + tcp_send(sock, req); + tcp_receive(sock, buf, BUF_SIZE); + tcp_close(sock); + } + + free(req); + + return sock != -1 && strstr(buf, "Ok.") != NULL; +} + +bool send_radmon(const char *user, const char *pass, int cpm, const struct tm *tm) { + char ch[22], *req; + int sock; + char buf[BUF_SIZE] = { 0 }; + + strftime(ch, 22, "%Y-%m-%d%%20%H:%M:%S", tm); + asprintf(&req, "GET /radmon.php?user=%s&password=%s&function=submit&datetime=%s&value=%d&unit=CPM HTTP/1.1\r\nHost: www.radmon.org\r\n\r\n", user, pass, ch, cpm); + + if ((sock = tcp_connect("www.radmon.org", "80")) != -1) { + tcp_send(sock, req); + tcp_receive(sock, buf, BUF_SIZE); + tcp_close(sock); + } + + free(req); + + return sock != -1 && strstr(buf, "Incorrect login.") == NULL; +} + +bool send_safecast(const char *key, unsigned int dev, int cpm, const struct tm *tm, float lat, float lng, const char *loc) { + char ch[21], *pld, *req; + int sock; + char buf[BUF_SIZE] = { 0 }; + + strftime(ch, 21, "%Y-%m-%dT%H:%M:%SZ", tm); + asprintf(&pld, "{\"latitude\":\"%.4f\",\"longitude\":\"%.4f\",\"location_name\":\"%s\",\"device_id\":\"%u\",\"captured_at\":\"%s\",\"value\":\"%d\",\"unit\":\"cpm\"}", lat, lng, loc, dev, ch, cpm); + asprintf(&req, "POST /measurements.json?api_key=%s HTTP/1.1\r\nHost: api.safecast.org\r\nContent-Type: application/json\r\nContent-Length: %zu\r\n\r\n%s", key, strlen(pld), pld); + + if ((sock = tcp_connect("api.safecast.org", "80")) != -1) { + tcp_send(sock, req); + tcp_receive(sock, buf, BUF_SIZE); + tcp_close(sock); + } + + free(pld); + free(req); + + return sock != -1 && strstr(buf, "201 Created") != NULL; +} + +void print_usage() { + printf(" ___ Geiger Counter LOGger daemon\n"); + printf(" \\_/ Version %s (Build %s)\n", GCLOG_VERSION, GCLOG_BUILD); + printf(".--,O.--,\n"); + printf(" \\/ \\/ Copyright (C) 2014-16 Steffen Lange, gclog@stelas.de\n\n"); + printf("This program comes with ABSOLUTELY NO WARRANTY.\n"); + printf("This is free software, and you are welcome to redistribute it\n"); + printf("under certain conditions. See the file COPYING for details.\n\n"); + printf("Usage: gclog -c [-d]\n"); + printf(" -c load configuration from file\n"); + printf(" -d activate verbose mode\n\n"); +} + +int main(int argc, char *argv[]) { + bool debug = false; + unsigned int interval = 60; + enum EGeiger device_type = SIM; + char *device_port = NULL; + float latitude = 0.0, longitude = 0.0; + char *location = NULL; + char *netc_id = NULL; + char *radmon_user = NULL, *radmon_pass = NULL; + char *safecast_key = NULL; + unsigned int safecast_device = 0; + + print_usage(); + + pid_t pid; + + if ((pid = fork()) == -1) { + fprintf(stderr, "%s: fork() failed.\n", argv[0]); + exit(EXIT_FAILURE); + } + if (pid > 0) { + // Luke, I'm your father. + exit(EXIT_SUCCESS); + } + + if (setsid() == -1) { + fprintf(stderr, "%s: setsid() failed.\n", argv[0]); + exit(EXIT_FAILURE); + } + + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGQUIT, signal_handler); + signal(SIGHUP, signal_handler); + + log_open("gclog"); + + int opt; + struct map_t *ini; + char *val; + + while ((opt = getopt(argc, argv, "c:d")) != -1) { + switch (opt) { + case 'd': + debug = true; + break; + + case 'c': + ini = load_ini(optarg); + if ((val = map_get(ini, "interval")) != NULL) + interval = MAX(atoi(val), 1); + if ((val = map_get(ini, "device.type")) != NULL) { + if (strcmp(val, "sim") == 0) + device_type = SIM; + else if (strcmp(val, "diy") == 0) + device_type = DIY; + else if (strcmp(val, "gq") == 0) + device_type = GQ; + } + if ((val = map_get(ini, "device.port")) != NULL) + device_port = string_copy(val); + if ((val = map_get(ini, "latitude")) != NULL) + latitude = MIN(MAX(atof(val), -90.0), 90.0); + if ((val = map_get(ini, "longitude")) != NULL) + longitude = MIN(MAX(atof(val), -180.0), 180.0); + if ((val = map_get(ini, "location")) != NULL) + location = string_copy(val); + if ((val = map_get(ini, "netc.id")) != NULL) + netc_id = string_copy(val); + if ((val = map_get(ini, "radmon.user")) != NULL) + radmon_user = string_copy(val); + if ((val = map_get(ini, "radmon.pass")) != NULL) + radmon_pass = string_copy(val); + if ((val = map_get(ini, "safecast.key")) != NULL) + safecast_key = string_copy(val); + if ((val = map_get(ini, "safecast.device")) != NULL) + safecast_device = atoi(val); + map_free(ini); + break; + + default: + break; + } + } + + if (debug) + printf("Configuration:\n\t\t%s on %s,\n\t\tLocation: %s (%f, %f)\n\t\tnetc.com: %s,\n\t\tradmon.org: %s / %s,\n\t\tsafecast.org: %s (Device ID %u),\n\t\t%us interval\n\n", GeigerNames[device_type], device_port, location, latitude, longitude, netc_id, radmon_user, radmon_pass, safecast_key, safecast_device, interval); + + int fd = -1; + + if (string_isset(device_port) && ((fd = geiger_open(device_type, device_port)) != -1)) { + fclose(stdin); + fclose(stdout); + fclose(stderr); + + time_t last = time(NULL); + int cpm, sum = 0, count = 0; + + while (Running) { + if ((cpm = geiger_get_cpm(device_type, fd)) > 0) { + sum += cpm; + count++; + } + + if (difftime(time(NULL), last) >= interval) { + if (count > 0) { + struct tm *tm = gmtime(&last); + cpm = div_round_closest(sum, count); + + if (debug) { + char *cpmstr; + asprintf(&cpmstr, "CPM: %d (= %d/%d), Timestamp: %s", cpm, sum, count, asctime(tm)); + log_inform(cpmstr); + free(cpmstr); + } + + if (string_isset(netc_id)) + if(!send_netc(netc_id, cpm)) + log_warn("Upload to netc.com failed."); + if (string_isset(radmon_user) && string_isset(radmon_pass)) + if (!send_radmon(radmon_user, radmon_pass, cpm, tm)) + log_warn("Upload to radmon.org failed."); + if (string_isset(safecast_key) && string_isset(location)) + if(!send_safecast(safecast_key, safecast_device, cpm, tm, latitude, longitude, location)) + log_warn("Upload to safecast.org failed."); + + time(&last); + sum = count = 0; + } + else + log_exclaim("Reading ZERO value from Geiger tube."); + } + + // Let the cpu breathe. + sleep(1); + } + + geiger_close(device_type, fd); + } + else + perror("FATAL ERROR: Could not access Geiger counter"); + + try_free(device_port); + try_free(location); + try_free(netc_id); + try_free(radmon_user); + try_free(radmon_pass); + try_free(safecast_key); + + log_close(); + + return fd == -1 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/gclog.conf b/gclog.conf new file mode 100644 index 0000000..edcfb18 --- /dev/null +++ b/gclog.conf @@ -0,0 +1,45 @@ +############################################ +# Geiger Counter LOGger configuration file # +############################################ + +# Geiger counter type: +# 'gq' -> GQ GMC Geiger Counter (GQ-RFC1201 protocol) +# 'diy' -> DIY/MyGeiger/NET-IO Geiger Kit or compatible +######################################################## +#device.type=diy +device.type=gq + +# Serial device filename +######################## +device.port=/dev/ttyUSB0 + +# GPS location of your sensor; required for Safecast +#################################################### +location=Berlin, DE +latitude=52.5163 +longitude=13.3777 + +# Polling interval in seconds (60..3600) +######################################## +interval=60 + +######################################################################### +# radmon.org # +# Enter your forum nickname and password received via PM from 'mw0uzo'. # +######################################################################### +#radmon.user=mynick +#radmon.pass=mypass + +################################################ +# Safecast.org # +# Your API key is listed on your profile page. # +# Find your device ID on the Safecast list. # +################################################ +#safecast.key=abcdefghijklmnopqrst +#safecast.device=108 + +################################################################################ +# Nuclear Emergency Tracking Center (NETC.com) # +# First use their 'wapp4netc.exe' software to register your Geiger counter ID. # +################################################################################ +#netc.id=ABCDEF012 diff --git a/gclog.spec b/gclog.spec new file mode 100644 index 0000000..80b64ae --- /dev/null +++ b/gclog.spec @@ -0,0 +1,52 @@ +Name: gclog +Version: 0.2.3 +Release: 1%{?dist} +Summary: Geiger Counter Logger +License: GPLv3 +Group: Applications/System +Url: http://www.dateihal.de/cms/gclog +Source0: http://www.dateihal.de/%{name}/%{name}-%{version}.tar.gz + +%description +GCLOG is a lightweight daemon running in the background and +constantly reporting your Geiger counter readings to various +radiation monitoring websites. + +%prep +%setup -q + +%build +make %{?_smp_mflags} + +%install +make install DESTDIR=%{buildroot} + +%clean +make clean + +%preun +/sbin/service gclogd stop || : +if [ "$1" = "0" ]; then +/sbin/chkconfig --del gclogd +fi + +%post +if [ "$1" = "1" ]; then +/sbin/chkconfig --add gclogd +fi + +%files +%defattr(-, root, root) +%{_bindir}/gclog +%{_sysconfdir}/init.d/gclogd +%config(noreplace) %{_sysconfdir}/gclog.conf +%{_mandir}/man1/gclog.1* +%doc README* CHANGELOG TODO COPYING + +%changelog +* Sun Feb 28 2016 Steffen Lange 0.2.3-1 +- Minor fixes +* Sat Apr 25 2015 Steffen Lange 0.2.2-1 +- New upstream release +* Wed Mar 18 2015 Steffen Lange 0.2.1-1 +- Initial package of version 0.2.1 diff --git a/gclogd b/gclogd new file mode 100755 index 0000000..f77a925 --- /dev/null +++ b/gclogd @@ -0,0 +1,30 @@ +#!/bin/sh +# chkconfig: 235 80 20 +### BEGIN INIT INFO +# Provides: gclogd +# Required-Start: $network $remote_fs +# Required-Stop: $network $remote_fs +# Default-Start: 2 3 5 +# Default-Stop: 0 1 6 +# Short-Description: Geiger Counter Logger +### END INIT INFO + +case "$1" in + start) + /usr/bin/gclog -c /etc/gclog.conf + ;; + stop) + /usr/bin/killall gclog + ;; + force-reload|restart) + $0 stop + sleep 1 + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/gqgeiger.c b/gqgeiger.c new file mode 100644 index 0000000..b19ac35 --- /dev/null +++ b/gqgeiger.c @@ -0,0 +1,113 @@ +#include "gqgeiger.h" + +int gq_open(const char *device) { + int fd = -1; + struct termios tio; + + memset(&tio, 0, sizeof(struct termios)); + tio.c_cflag = CS8 | CREAD | CLOCAL; // 8n1 + tio.c_cc[VMIN] = 0; + tio.c_cc[VTIME] = 5; + + if ((fd = open(device, O_RDWR)) != -1) { + if (cfsetspeed(&tio, B57600) == 0) // 57600 baud + if (tcsetattr(fd, TCSANOW, &tio) == 0) + // Turn off heartbeat, + if (gq_set_heartbeat_off(fd)) + return fd; + + // ... otherwise close device. + close(fd); + fd = -1; + } + + return fd; +} + +void gq_close(int device) { + close(device); +} + +int gq_get_cpm(int device) { + const char cmd[] = ">"; + char buf[3] = { 0 }; + + if (gq_write(device, cmd) == (ssize_t) strlen(cmd)) + gq_read(device, buf, 2); + + return buf[0] * 256 + buf[1]; +} + +bool gq_set_heartbeat_off(int device) { + const char cmd[] = ">"; + + if (gq_write(device, cmd) == (ssize_t) strlen(cmd)) + return gq_flush(device); + + return false; +} + +bool gq_set_date(int device, int year, int month, int day) { + char y[] = ">"; + char m[] = ">"; + char d[] = ">"; + + y[10] = year - 2000; + m[10] = month; + d[10] = day; + + return gq_write_ack(device, y) && gq_write_ack(device, m) && gq_write_ack(device, d); +} + +bool gq_set_time(int device, int hour, int minute, int second) { + char h[] = ">"; + char m[] = ">"; + char s[] = ">"; + + h[10] = hour; + m[10] = minute; + s[10] = second; + + return gq_write_ack(device, h) && gq_write_ack(device, m) && gq_write_ack(device, s); +} + +bool gq_write_ack(int device, const char *cmd) { + char ch; + + if (gq_write(device, cmd) == (ssize_t) strlen(cmd)) + if (gq_read(device, &ch, 1) == 1 && ch == '\xAA') + return true; + + return false; +} + +int gq_write(int device, const char *cmd) { + return write(device, cmd, strlen(cmd)); +} + +int gq_read(int device, char *buf, unsigned int len) { + unsigned int n; + ssize_t rcvd = 0; + char *inp = &buf[0]; + + for (n = 0; n < len; n++) { + rcvd += read(device, inp, 1); + inp = &buf[rcvd]; + if (rcvd >= len) + break; + } + + return rcvd; +} + +bool gq_flush(int device) { + int i; + char ch; + + for (i = 0; i < 10; i++) { + if (read(device, &ch, 1) == 0) + return true; + } + + return false; +} diff --git a/gqgeiger.h b/gqgeiger.h new file mode 100644 index 0000000..7e5b35a --- /dev/null +++ b/gqgeiger.h @@ -0,0 +1,26 @@ +#ifndef _GQGEIGER_H_ +#define _GQGEIGER_H_ + +#include +#include +#include +#include +#include +#include + +/* + GQ Geiger Counter Communication Protocol: http://www.gqelectronicsllc.com/download/GQ-RFC1201.txt +*/ + +int gq_open(const char *device); +void gq_close(int device); +int gq_get_cpm(int device); +bool gq_set_heartbeat_off(int device); +bool gq_set_date(int device, int year, int month, int day); +bool gq_set_time(int device, int hour, int minute, int second); +bool gq_write_ack(int device, const char *cmd); +int gq_write(int device, const char *cmd); +int gq_read(int device, char *buf, unsigned int len); +bool gq_flush(int device); + +#endif diff --git a/ini.c b/ini.c new file mode 100644 index 0000000..d2e393f --- /dev/null +++ b/ini.c @@ -0,0 +1,33 @@ +#include "ini.h" + +struct map_t * load_ini(const char *file) { + struct map_t *map; + FILE *fh; + char buf[INI_LINELEN]; + char *s, *val; + + map = map_create(); + + if ((fh = fopen(file, "r"))) { + while (fgets(buf, INI_LINELEN, fh)) { + // Chomp newline. + buf[strlen(buf) - 1] = '\0'; + + // Suppress comment. + if ((s = strchr(buf, '#'))) + *s = '\0'; + + if ((val = strchr(buf, '='))) { + // Split into trimmed key and value... + *val++ = '\0'; + s = trim(buf); + trim(val); + // ...and store in map. + map_set(map, s, val); + } + } + fclose(fh); + } + + return map; +} diff --git a/ini.h b/ini.h new file mode 100644 index 0000000..eb7d8f8 --- /dev/null +++ b/ini.h @@ -0,0 +1,12 @@ +#ifndef _INI_H_ +#define _INI_H_ + +#include +#include "trim.h" +#include "map.h" + +#define INI_LINELEN 100 + +struct map_t * load_ini(const char *file); + +#endif diff --git a/logger.c b/logger.c new file mode 100644 index 0000000..b639b6f --- /dev/null +++ b/logger.c @@ -0,0 +1,21 @@ +#include "logger.h" + +void log_open(const char *name) { + openlog(name, LOG_CONS | LOG_PID, LOG_LOCAL3); +} + +void log_close() { + closelog(); +} + +void log_inform(const char *msg) { + syslog(LOG_NOTICE, "%s", msg); +} + +void log_warn(const char *msg) { + syslog(LOG_WARNING, "[WARNING] %s", msg); +} + +void log_exclaim(const char *msg) { + syslog(LOG_ERR, "[ERROR] %s", msg); +} diff --git a/logger.h b/logger.h new file mode 100644 index 0000000..f18daed --- /dev/null +++ b/logger.h @@ -0,0 +1,12 @@ +#ifndef _LOGGER_H_ +#define _LOGGER_H_ + +#include + +void log_open(const char *name); +void log_close(); +void log_inform(const char *msg); +void log_warn(const char *msg); +void log_exclaim(const char *msg); + +#endif diff --git a/map.c b/map.c new file mode 100644 index 0000000..f32b116 --- /dev/null +++ b/map.c @@ -0,0 +1,61 @@ +#include "map.h" + +struct map_t * map_create() { + return calloc(1, sizeof(struct map_t)); +} + +void map_free(struct map_t *map) { + struct map_t *m, *tmp; + + m = map; + while (m) { + if (m->key) + free(m->key); + if (m->value) + free(m->value); + tmp = m; + m = m->next; + free(tmp); + } +} + +char * map_get(struct map_t *map, const char *key) { + struct map_t *m; + + for (m = map; m != NULL; m = m->next) { + if (m->key && !strcasecmp(key, m->key)) + return m->value; + } + + return NULL; +} + +void map_set(struct map_t *map, const char *key, const char *val) { + struct map_t *m; + + m = map; + + // Map not empty? + if (m->key) { + for ( ; ; m = m->next) { + // Key exists, freeing strings for reuse. + if (!strcasecmp(key, m->key)) { + free(m->key); + free(m->value); + break; + } + // Last element, adding a new one. + else if (!m->next) { + m->next = calloc(1, sizeof(struct map_t)); + m = m->next; + break; + } + } + } + + // Add key and value. + m->key = calloc(strlen(key) + 1, sizeof(char)); + strcpy(m->key, key); + m->value = calloc(strlen(val) + 1, sizeof(char)); + strcpy(m->value, val); +} diff --git a/map.h b/map.h new file mode 100644 index 0000000..20a880f --- /dev/null +++ b/map.h @@ -0,0 +1,18 @@ +#ifndef _MAP_H_ +#define _MAP_H_ + +#include +#include + +struct map_t { + char *key; + char *value; + struct map_t *next; +}; + +struct map_t * map_create(); +void map_free(struct map_t *map); +char * map_get(struct map_t *map, const char *key); +void map_set(struct map_t *map, const char *key, const char *val); + +#endif diff --git a/openwrt/Makefile b/openwrt/Makefile new file mode 100644 index 0000000..1d35b1c --- /dev/null +++ b/openwrt/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=gclog +PKG_VERSION:=0.2.3 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.dateihal.de/$(PKG_NAME) +#PKG_MD5SUM:= + +include $(INCLUDE_DIR)/package.mk + +define Package/gclog + SECTION:=utils + CATEGORY:=Utilities + TITLE:=Geiger Counter Logger + URL:=http://www.dateihal.de/cms/gclog + MAINTAINER:=Steffen Lange +endef + +define Package/gclog/description + GCLOG is a lightweight daemon running in the background and + constantly reporting your Geiger counter readings to various + radiation monitoring websites. +endef + +define Package/gclog/conffiles +/etc/gclog.conf +endef + +define Package/gclog/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_DIR) $(1)/etc + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) $(PKG_BUILD_DIR)/gclog $(1)/usr/bin/ + $(INSTALL_CONF) $(PKG_BUILD_DIR)/gclog.conf $(1)/etc/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/openwrt/gclogd $(1)/etc/init.d/ +endef + +$(eval $(call BuildPackage,gclog)) diff --git a/openwrt/buildenv.sh b/openwrt/buildenv.sh new file mode 100755 index 0000000..926f4da --- /dev/null +++ b/openwrt/buildenv.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Setup buildroot +# --------------- +# 1. Download OpenWrt SDK, ex. Barrier Breaker 14.07 for ar71xx architecture: +# http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2 +# 2. Extract archive to ~/OpenWrt +# 3. Modify toolchain path if needed +# 4. Execute "source buildenv.sh" + +export STAGING_DIR="~/OpenWrt/staging_dir" +export CC="${STAGING_DIR}/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc" + +echo 'Build environment set, now run "make".' diff --git a/openwrt/gclogd b/openwrt/gclogd new file mode 100755 index 0000000..51cca2c --- /dev/null +++ b/openwrt/gclogd @@ -0,0 +1,16 @@ +#!/bin/sh /etc/rc.common +# GCLOG init script +# Copyright (C) 2007 OpenWrt.org + +START=99 +STOP=20 + +start() { + echo start + /usr/bin/gclog -c /etc/gclog.conf +} + +stop() { + echo stop + /usr/bin/killall gclog +} diff --git a/tcpcli.c b/tcpcli.c new file mode 100644 index 0000000..0b3f331 --- /dev/null +++ b/tcpcli.c @@ -0,0 +1,38 @@ +#include "tcpcli.h" + +int tcp_connect(const char *host, const char *port) { + int sock = -1; + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; // AF_INET, AF_INET6 or AF_UNSPEC + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(host, port, &hints, &res) == 0) { + if ((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) != -1) + if (connect(sock, res->ai_addr, res->ai_addrlen) == -1) { + close(sock); + sock = -1; + } + freeaddrinfo(res); + } + + return sock; +} + +void tcp_close(int sock) { + close(sock); +} + +int tcp_send(int sock, const char *str) { + return send(sock, str, strlen(str), 0); +} + +int tcp_receive(int sock, char *buffer, unsigned int size) { + ssize_t n; + + if ((n = recv(sock, buffer, size - 1, 0)) >= 0) + buffer[n] = '\0'; // Terminate string. + + return n; +} diff --git a/tcpcli.h b/tcpcli.h new file mode 100644 index 0000000..24958a3 --- /dev/null +++ b/tcpcli.h @@ -0,0 +1,15 @@ +#ifndef _TCPCLI_H_ +#define _TCPCLI_H_ + +#include +#include +#include +#include +#include + +int tcp_connect(const char *host, const char *port); +void tcp_close(int sock); +int tcp_send(int sock, const char *str); +int tcp_receive(int sock, char *buffer, unsigned int size); + +#endif diff --git a/trim.c b/trim.c new file mode 100644 index 0000000..4c6333d --- /dev/null +++ b/trim.c @@ -0,0 +1,31 @@ +#include "trim.h" + +char * ltrim(char *s) { + char *start = s; + + // Find first non-whitespace character. + while (isspace(*start)) + start++; + + // Move string part to beginning, including null terminator. + memmove(s, start, strlen(start) + 1); + + return s; +} + +char * rtrim(char *s) { + char *end = s + strlen(s); + + // Find last non-whitespace character. + while ((end != s) && isspace(*(end - 1))) + end--; + + // Mark new string endpoint. + *end = '\0'; + + return s; +} + +char * trim(char *s) { + return ltrim(rtrim(s)); +} diff --git a/trim.h b/trim.h new file mode 100644 index 0000000..4d65e79 --- /dev/null +++ b/trim.h @@ -0,0 +1,11 @@ +#ifndef _TRIM_H_ +#define _TRIM_H_ + +#include +#include + +char * ltrim(char *s); +char * rtrim(char *s); +char * trim(char *s); + +#endif