From fdc52ee122d057a153966355b920f5a6170ff2b6 Mon Sep 17 00:00:00 2001 From: Roland Jax Date: Mon, 14 Apr 2014 23:40:45 +0200 Subject: [PATCH] initial commit --- .gitignore | 17 + AUTHORS | 1 + COPYING | 674 ++++++++++++++++++++++ ChangeLog | 3 + Makefile.am | 30 + NEWS | 0 README | 4 + autogen.sh | 6 + contrib/csv/vaillant/ci.csv | 58 ++ contrib/csv/vaillant/ci.ods | Bin 0 -> 19166 bytes contrib/csv/vaillant/old/vaillant_cyc.csv | 14 + contrib/csv/vaillant/old/vaillant_cyc.ods | Bin 0 -> 14106 bytes contrib/csv/vaillant/old/vaillant_get.csv | 244 ++++++++ contrib/csv/vaillant/old/vaillant_get.ods | Bin 0 -> 20824 bytes contrib/csv/vaillant/old/vaillant_set.csv | 95 +++ contrib/csv/vaillant/old/vaillant_set.ods | Bin 0 -> 20808 bytes contrib/csv/vaillant/vpm20s.csv | 16 + contrib/csv/vaillant/vpm20s.ods | Bin 0 -> 14451 bytes contrib/csv/vaillant/vpm3035w.csv | 20 + contrib/csv/vaillant/vpm3035w.ods | Bin 0 -> 17230 bytes contrib/csv/vaillant/vr603.csv | 51 ++ contrib/csv/vaillant/vr603.ods | Bin 0 -> 20495 bytes contrib/csv/vaillant/vr903.csv | 6 + contrib/csv/vaillant/vr903.ods | Bin 0 -> 15028 bytes contrib/csv/vaillant/vwx.csv | 107 ++++ contrib/csv/vaillant/vwx.ods | Bin 0 -> 20557 bytes contrib/csv/wolf/wolf_cycle.csv | 8 + contrib/csv/wolf/wolf_cycle.ods | Bin 0 -> 26080 bytes src/baseloop.cpp | 154 +++++ src/baseloop.h | 92 +++ src/cycdata.cpp | 88 +++ src/cycdata.h | 56 ++ src/ebusloop.cpp | 110 ++++ src/ebusloop.h | 57 ++ src/main.cpp | 222 +++++++ src/network.cpp | 220 +++++++ src/network.h | 84 +++ test/feed.cpp | 99 ++++ test/scan_ebusd.bin | Bin 0 -> 18 bytes utils/appl.cpp | 161 ++++++ utils/appl.h | 102 ++++ utils/daemon.cpp | 117 ++++ utils/daemon.h | 48 ++ utils/logger.cpp | 201 +++++++ utils/logger.h | 177 ++++++ utils/notify.h | 56 ++ utils/tcpsocket.cpp | 92 +++ utils/tcpsocket.h | 77 +++ utils/thread.cpp | 84 +++ utils/thread.h | 46 ++ utils/wqueue.h | 85 +++ 51 files changed, 3782 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100755 autogen.sh create mode 100644 contrib/csv/vaillant/ci.csv create mode 100644 contrib/csv/vaillant/ci.ods create mode 100644 contrib/csv/vaillant/old/vaillant_cyc.csv create mode 100644 contrib/csv/vaillant/old/vaillant_cyc.ods create mode 100644 contrib/csv/vaillant/old/vaillant_get.csv create mode 100644 contrib/csv/vaillant/old/vaillant_get.ods create mode 100644 contrib/csv/vaillant/old/vaillant_set.csv create mode 100644 contrib/csv/vaillant/old/vaillant_set.ods create mode 100644 contrib/csv/vaillant/vpm20s.csv create mode 100644 contrib/csv/vaillant/vpm20s.ods create mode 100644 contrib/csv/vaillant/vpm3035w.csv create mode 100644 contrib/csv/vaillant/vpm3035w.ods create mode 100644 contrib/csv/vaillant/vr603.csv create mode 100644 contrib/csv/vaillant/vr603.ods create mode 100644 contrib/csv/vaillant/vr903.csv create mode 100644 contrib/csv/vaillant/vr903.ods create mode 100644 contrib/csv/vaillant/vwx.csv create mode 100644 contrib/csv/vaillant/vwx.ods create mode 100644 contrib/csv/wolf/wolf_cycle.csv create mode 100644 contrib/csv/wolf/wolf_cycle.ods create mode 100644 src/baseloop.cpp create mode 100644 src/baseloop.h create mode 100644 src/cycdata.cpp create mode 100644 src/cycdata.h create mode 100644 src/ebusloop.cpp create mode 100644 src/ebusloop.h create mode 100644 src/main.cpp create mode 100644 src/network.cpp create mode 100644 src/network.h create mode 100644 test/feed.cpp create mode 100644 test/scan_ebusd.bin create mode 100644 utils/appl.cpp create mode 100644 utils/appl.h create mode 100644 utils/daemon.cpp create mode 100644 utils/daemon.h create mode 100644 utils/logger.cpp create mode 100644 utils/logger.h create mode 100644 utils/notify.h create mode 100644 utils/tcpsocket.cpp create mode 100644 utils/tcpsocket.h create mode 100644 utils/thread.cpp create mode 100644 utils/thread.h create mode 100644 utils/wqueue.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6e9b6338 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +/INSTALL +/Makefile +/Makefile.in +/aclocal.m4 +/autom4te.cache/ +/config* +/depcomp +/ebus-daemon +/ebus-daemon*.tar.* +/install-sh +/missing +/stamp-h? +.deps/ +*.o +*.dirstamp +/compile +/feed diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..f24a463e --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Roland Jax diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..94a9ed02 --- /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/ChangeLog b/ChangeLog new file mode 100644 index 00000000..5af6adfb --- /dev/null +++ b/ChangeLog @@ -0,0 +1,3 @@ +2014-01-09 Roland Jax + + * Initial commit. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..d8d36187 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,30 @@ +AUTOMAKE_OPTIONS = subdir-objects + +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +AM_CXXFLAGS = $(LIBEBUS_CFLAGS) -I$(top_srcdir)/utils -fpic -Wall -Wextra + +bin_PROGRAMS = ebus-daemon + +ebus_daemon_SOURCES = src/main.cpp \ + src/baseloop.cpp \ + src/ebusloop.cpp \ + src/cycdata.cpp \ + src/network.cpp \ + utils/thread.cpp \ + utils/logger.cpp \ + utils/tcpsocket.cpp \ + utils/daemon.cpp \ + utils/appl.cpp + +ebus_daemon_LDADD = $(LIBEBUS_LIBS) \ + -lpthread + +dist_noinst_SCRIPTS = autogen.sh + +noinst_PROGRAMS = feed + +feed_SOURCES = test/feed.cpp \ + utils/appl.cpp + +feed_LDADD = $(LIBEBUS_LIBS) diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/README b/README new file mode 100644 index 00000000..1e6cf141 --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +ebusd +----- + +Daemon to communicate with ebus based heating systems. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..2d8179c1 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,6 @@ +#!/bin/sh -e +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. + +autoreconf --force --install --verbose "$srcdir" +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/contrib/csv/vaillant/ci.csv b/contrib/csv/vaillant/ci.csv new file mode 100644 index 00000000..d3137d6b --- /dev/null +++ b/contrib/csv/vaillant/ci.csv @@ -0,0 +1,58 @@ +# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +get;ci;HydraulicMap;Hydraulikplan;MS;15;B509;3;0D2900;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;Language;Sprache;MS;15;B509;3;0D2600;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;HolidayPeriod;Ferien Zeitraum;MS;15;B509;3;0D4300;4;start1;sd;1,2,3;hda;-;-;-;Start 1;start2;sd;5,6,4;hda;-;-;-;Start 2;end1;sd;7,8,9;hda;-;-;-;Ende 1;end2;sd;11,12,10;hda;-;-;-;Ende 2 +get;ci;HolidayRoomSetTemp;Ferien Solltemperatur;MS;15;B509;3;0D2200;1;-;sd;1,2;d2c;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;Password;Kennwort;MS;15;B509;3;0D2C00;4;pin1;sd;1;uch;-;-;-;Pin 1;pin2;sd;2;uch;-;-;-;Pin 2;pin3;sd;3;uch;-;-;-;Pin 3;pin4;sd;4;uch;-;-;-;Pin 4 +get;ci;DesiredTemp;Solltemperatur;MS;15;B509;3;0D0500;1;-;sd;1,2;d2c;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;FlowTempSensor;Vorlauftemperatur Ist;MS;15;B509;3;0D0200;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;ci;HeatingTimeMaxHotWaterRequest;Heizzeit MAX bei Warmwasseranforderung;MS;15;B509;3;0D4D00;1;-;sd;1;uch;-;min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;LoadingTimeMaxHeatRequest;Ladezeit MAX bei Heizanforderung;MS;15;B509;3;0D4C00;1;-;sd;1;uch;-;min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;TempIncrease;Temperaturüberhöhung;MS;15;B509;3;0D2F00;1;-;sd;1,2;d2c;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;PreTurnOffTime;Vorabschaltzeit;MS;15;B509;3;0D2D00;1;-;sd;1;uch;-;min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;FrostProtectionDelayTime;Frostschutzverzögerung;MS;15;B509;3;0D2E00;1;-;sd;1;uch;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;TempErrorDetectTime;Temperaturfehlererkennung;MS;15;B509;3;0D3300;1;-;sd;1;uch;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit2;Name Heizkreis 2;MS;15;B509;3;0D4108;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit4;Name Heizkreis 4;MS;15;B509;3;0D4118;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit5;Name Heizkreis 5;MS;15;B509;3;0D4120;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit6;Name Heizkreis 6;MS;15;B509;3;0D4128;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit7;Name Heizkreis 7;MS;15;B509;3;0D4130;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit8;Name Heizkreis 8;MS;15;B509;3;0D4138;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit9;Name Heizkreis 9;MS;15;B509;3;0D4140;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit10;Name Heizkreis 10;MS;15;B509;3;0D4148;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit11;Name Heizkreis 11;MS;15;B509;3;0D4150;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit12;Name Heizkreis 12;MS;15;B509;3;0D4158;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit13;Name Heizkreis 13;MS;15;B509;3;0D4160;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit14;Name Heizkreis 14;MS;15;B509;3;0D4168;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit15;Name Heizkreis 15;MS;15;B509;3;0D4170;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;NameHeatCircuit16;Name Heizkreis 16;MS;15;B509;3;0D4178;1;-;sd;1,10;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;PhoneNumber1;Telefonnummer 1;MS;15;B509;3;0D4200;1;-;sd;1,9;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;PhoneNumber2;Telefonnummer 2;MS;15;B509;3;0D4208;1;-;sd;1,9;str;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;HeatBufferAvailable;Bufferspeicher vorhanden;MS;15;B509;3;0D5C00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear1;Energieertrag aktuelles Jahr Monat 1;MS;15;B509;3;0D8400;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear2;Energieertrag aktuelles Jahr Monat 2;MS;15;B509;3;0D8408;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear3;Energieertrag aktuelles Jahr Monat 3;MS;15;B509;3;0D8410;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear4;Energieertrag aktuelles Jahr Monat 4;MS;15;B509;3;0D8418;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear5;Energieertrag aktuelles Jahr Monat 5;MS;15;B509;3;0D8420;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear6;Energieertrag aktuelles Jahr Monat 6;MS;15;B509;3;0D8428;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear7;Energieertrag aktuelles Jahr Monat 7;MS;15;B509;3;0D8430;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear8;Energieertrag aktuelles Jahr Monat 8;MS;15;B509;3;0D8438;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear9;Energieertrag aktuelles Jahr Monat 9;MS;15;B509;3;0D8440;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear10;Energieertrag aktuelles Jahr Monat 10;MS;15;B509;3;0D8448;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear11;Energieertrag aktuelles Jahr Monat 11;MS;15;B509;3;0D8450;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldThisYear12;Energieertrag aktuelles Jahr Monat 12;MS;15;B509;3;0D8458;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear1;Energieertrag letztes Jahr Monat 1;MS;15;B509;3;0D8500;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear2;Energieertrag letztes Jahr Monat 2;MS;15;B509;3;0D8508;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear3;Energieertrag letztes Jahr Monat 3;MS;15;B509;3;0D8510;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear4;Energieertrag letztes Jahr Monat 4;MS;15;B509;3;0D8518;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear5;Energieertrag letztes Jahr Monat 5;MS;15;B509;3;0D8520;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear6;Energieertrag letztes Jahr Monat 6;MS;15;B509;3;0D8528;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear7;Energieertrag letztes Jahr Monat 7;MS;15;B509;3;0D8530;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear8;Energieertrag letztes Jahr Monat 8;MS;15;B509;3;0D8538;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear9;Energieertrag letztes Jahr Monat 9;MS;15;B509;3;0D8540;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear10;Energieertrag letztes Jahr Monat 10;MS;15;B509;3;0D8548;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear11;Energieertrag letztes Jahr Monat 11;MS;15;B509;3;0D8550;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldLastYear12;Energieertrag letztes Jahr Monat 12;MS;15;B509;3;0D8558;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldDayTransfer;Energieertrag Tagesübertrag;MS;15;B509;3;0D8600;1;-;sd;1,2,3,4;ulg;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;EnergyYieldSum;Energieertrag Gesamt;MS;15;B509;3;0D8700;1;-;sd;1,2,3,4;ulg;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;ci;SystemMode;Modus (Heizen/Kühlen/Warmwasser);MS;15;B509;3;0D9700;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/ci.ods b/contrib/csv/vaillant/ci.ods new file mode 100644 index 0000000000000000000000000000000000000000..69613923c51f7ee21e7aa469e45c15bd4f5ad4d3 GIT binary patch literal 19166 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 literal 0 HcmV?d00001 diff --git a/contrib/csv/vaillant/old/vaillant_cyc.csv b/contrib/csv/vaillant/old/vaillant_cyc.csv new file mode 100644 index 00000000..041e42ae --- /dev/null +++ b/contrib/csv/vaillant/old/vaillant_cyc.csv @@ -0,0 +1,14 @@ +# type;class;cmd;comment;msg type: 1=BROAD, 2=MM, 3=MS;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +cyc;broad;date_time_temp;Datum, Uhrzeit und Aussentempertur;BR;FE;0700;9;-;4;temp;md;1,2;d2b;1.0;°C;-;Temperatur;day;md;8;bdy;-;-;-;Wochentag;date;md;6,7,9;bda;-;-;-;Datum;time;md;5,4,3;bti;-;-;-;Uhrzeit +cyc;broad;load_VF_temp;Speicherladung und Vorlauftempertur;BR;FE;B505;4;27;3;load;md;2;bcd;1.0;-;00,01;Speicherladung;temp;md;3;d1c;1.0;°C;-;Temperatur;stat;md;4;bcd;1.0;-;-;Status;;;;;;;; +cyc;broad;date_time;Datum, Uhrzeit;BR;FE;B516;8;00;3;day;md;7;hdy;-;-;-;Wochentag;date;md;5,6,8;bda;-;-;-;Datum;time;md;4,3,2;bti;-;-;-;Uhrzeit;;;;;;;; +cyc;broad;temp;Aussentemperatur;BR;FE;B516;3;01;1;-;md;2,3;d2b;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +cyc;mv;VF1_temp;Vorlauftemperatur VF1;MS;08;B509;3;290100;2;temp;sd;3,4;d2c;1.0;°C;-;Temperatur;stat;sd;5;bcd;1.0;-;-;Status;;;;;;;;;;;;;;;; +cyc;mv;RF1_temp;Rücklauftemperatur RF1;MS;08;B509;3;290700;2;temp;sd;3,4;d2c;1.0;°C;-;Temperatur;stat;sd;5;bcd;1.0;-;-;Status;;;;;;;;;;;;;;;; +cyc;mv;VF2_temp;Vorlauftemperatur VF2;MS;08;B509;3;290300;2;temp;sd;3,4;d2c;1.0;°C;-;Temperatur;stat;sd;5;bcd;1.0;-;-;Status;;;;;;;;;;;;;;;; +cyc;mv;brine_in;Quellentemperatur;MS;08;B509;3;290F00;2;temp;sd;3,4;d2c;1.0;°C;-;Temperatur;stat;sd;5;bcd;1.0;-;-;Status;;;;;;;;;;;;;;;; +cyc;amu;high_eff_pump_stat;Hocheffizenzpumpenstatus;MS;08;B509;3;29B801;1;-;sd;3;bcd;1.0;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +cyc;cir2;heat_pump_stat;Status Heizkreispumpe;MS;08;B509;3;29B901;1;-;sd;3;bcd;1.0;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +cyc;cir2;date_time_temp;Datum, Uhrzeit und Aussentempertur;MS;50;B504;1;00;4;day;sd;7;hdy;-;-;-;Wochentag;date;sd;5,6,8;bda;-;-;-;Datum;time;sd;4,3,2;bti;-;-;-;Uhrzeit;temp;sd;9,10;d2b;1.0;°C;-;Temperatur diff --git a/contrib/csv/vaillant/old/vaillant_cyc.ods b/contrib/csv/vaillant/old/vaillant_cyc.ods new file mode 100644 index 0000000000000000000000000000000000000000..f289937bac75e2453f9b2b72ef19e3f042d3ba44 GIT binary patch literal 14106 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 Kuehlung > Heizung;MS;50;B509;3;0D8401;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;locktime_heat>cool;Sperrzeit Heizung > Kühlung;MS;50;B509;3;0D8501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;min_diff;min Diff VL / RT;MS;50;B509;3;0D8B01;1;-;sd;1;d1c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;holiday_cooling;Kühlen im Ferienbetrieb;MS;50;B509;3;0D9501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;statbit_cooling;Statusbit Kühlfunktion;MS;50;B509;3;0D9701;1;-;sd;?;hex;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;cooling_request;HK spezifische Kühlanforderung?;MS;50;B509;3;0D8301;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;heat_pump_stat;Status Heizkreispumpe;MS;50;B509;3;0DB901;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;heat_pump_curr;akt. PWM-Wert Heizkreizpumpe;MS;50;B509;3;0DBA01;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;heat_pump_load;Heizkreispumpe bei Pufferladung;MS;50;B509;3;0DBF01;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;heat_pump_heat;Heizkreispumpe Standardwert;MS;50;B509;3;0DC001;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir2;heat_pump_pause;Heizkreispumpe in Pausen;MS;50;B509;3;0DE101;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# Heizkreis 4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;mode;Heizkreis - Betriebsart;MS;52;B509;3;0D2B00;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;type;Heizkreis - Kreis Typ;MS;52;B509;3;0D3C00;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;rt_day;Heizkreis – Raumsolltemperatur;MS;52;B509;3;0D3200;1;-;sd;1;d1b;0.500;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;rt_night;Heizkreis – Absenktemperatur;MS;52;B509;3;0D3300;1;-;sd;1;d1b;0.500;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;curve;Heizkreis – Heizkurve;MS;52;B509;3;0D3500;1;-;sd;1;d1b;0.010;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;at_off;Heizkreis – Aussentemperatur Abschaltgrenze;MS;52;B509;3;0D3600;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;vl_min;Heizkreis - minimale Vorlauftemperatur;MS;52;B509;3;0D3000;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;vl_max;Heizkreis - maximale Vorlauftemperatur;MS;52;B509;3;0D3100;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;pre_hours;Heizkreis - max. Voraufheizung in Stunden;MS;52;B509;3;0D3800;1;-;sd;1;bcd;1.000;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;estrich;Heizkreis Estrichtrocknung Tag;MS;52;B509;3;0D3B00;1;-;sd;1;bcd;1.000;dd;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;floor_protect;Fußbodenschutz;MS;52;B509;3;0D7B01;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;cooling;Kühlbetrieb;MS;52;B509;3;0D8C01;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;cooling_support;Kühlbetrieb supported/ für freigegeben;MS;52;B509;3;0D8601;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;outdoor_24h_average;Außentemperatur mittel 24h;MS;52;B509;3;0D8801;1;-;sd;1,2;d2c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;cooling_offset_outdoor;Kühlung Offset AT-Abschaltgrenze;MS;52;B509;3;0D8701;1;-;sd;1;d1c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;locktime_cool>heat;Sperrzeit Kuehlung > Heizung;MS;52;B509;3;0D8401;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;locktime_heat>cool;Sperrzeit Heizung > Kühlung;MS;52;B509;3;0D8501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;min_diff;min Diff VL / RT;MS;52;B509;3;0D8B01;1;-;sd;1;d1c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;holiday_cooling;Kühlen im Ferienbetrieb;MS;52;B509;3;0D9501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;statbit_cooling;Statusbit Kühlfunktion;MS;52;B509;3;0D9701;1;-;sd;?;hex;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;cooling_request;HK spezifische Kühlanforderung?;MS;52;B509;3;0D8301;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;heat_pump_stat;Status Heizkreispumpe;MS;52;B509;3;0DB901;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;heat_pump_curr;akt. PWM-Wert Heizkreizpumpe;MS;52;B509;3;0DBA01;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;heat_pump_load;Heizkreispumpe bei Pufferladung;MS;52;B509;3;0DBF01;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;heat_pump_heat;Heizkreispumpe Standardwert;MS;52;B509;3;0DC001;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir4;heat_pump_pause;Heizkreispumpe in Pausen;MS;52;B509;3;0DE101;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# Heizkreis 5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;mode;Heizkreis - Betriebsart;MS;53;B509;3;0D2B00;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;type;Heizkreis - Kreis Typ;MS;53;B509;3;0D3C00;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;rt_day;Heizkreis – Raumsolltemperatur;MS;53;B509;3;0D3200;1;-;sd;1;d1b;0.500;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;rt_night;Heizkreis – Absenktemperatur;MS;53;B509;3;0D3300;1;-;sd;1;d1b;0.500;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;curve;Heizkreis – Heizkurve;MS;53;B509;3;0D3500;1;-;sd;1;d1b;0.010;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;at_off;Heizkreis – Aussentemperatur Abschaltgrenze;MS;53;B509;3;0D3600;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;vl_min;Heizkreis - minimale Vorlauftemperatur;MS;53;B509;3;0D3000;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;vl_max;Heizkreis - maximale Vorlauftemperatur;MS;53;B509;3;0D3100;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;pre_hours;Heizkreis - max. Voraufheizung in Stunden;MS;53;B509;3;0D3800;1;-;sd;1;bcd;1.000;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;estrich;Heizkreis Estrichtrocknung Tag;MS;53;B509;3;0D3B00;1;-;sd;1;bcd;1.000;dd;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;floor_protect;Fußbodenschutz;MS;53;B509;3;0D7B01;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;cooling;Kühlbetrieb;MS;53;B509;3;0D8C01;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;cooling_support;Kühlbetrieb supported/ für freigegeben;MS;53;B509;3;0D8601;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;outdoor_24h_average;Außentemperatur mittel 24h;MS;53;B509;3;0D8801;1;-;sd;1,2;d2c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;cooling_offset_outdoor;Kühlung Offset AT-Abschaltgrenze;MS;53;B509;3;0D8701;1;-;sd;1;d1c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;locktime_cool>heat;Sperrzeit Kuehlung > Heizung;MS;53;B509;3;0D8401;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;locktime_heat>cool;Sperrzeit Heizung > Kühlung;MS;53;B509;3;0D8501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;min_diff;min Diff VL / RT;MS;53;B509;3;0D8B01;1;-;sd;1;d1c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;holiday_cooling;Kühlen im Ferienbetrieb;MS;53;B509;3;0D9501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;statbit_cooling;Statusbit Kühlfunktion;MS;53;B509;3;0D9701;1;-;sd;?;hex;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;cooling_request;HK spezifische Kühlanforderung?;MS;53;B509;3;0D8301;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +# ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;heat_pump_stat;Status Heizkreispumpe;MS;53;B509;3;0DB901;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;heat_pump_curr;akt. PWM-Wert Heizkreizpumpe;MS;53;B509;3;0DBA01;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;heat_pump_load;Heizkreispumpe bei Pufferladung;MS;53;B509;3;0DBF01;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;heat_pump_heat;Heizkreispumpe Standardwert;MS;53;B509;3;0DC001;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;cir5;heat_pump_pause;Heizkreispumpe in Pausen;MS;53;B509;3;0DE101;1;-;sd;1;d1b;1.000;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/old/vaillant_get.ods b/contrib/csv/vaillant/old/vaillant_get.ods new file mode 100644 index 0000000000000000000000000000000000000000..05cf37ab41b8ff9642e3ff2be77bc8ebf89db32d GIT binary patch literal 20824 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 z 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 Kuehlung > Heizung;MS;50;B509;4;0E8401;1;-;sd;1;bcd;1.000;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;cir2;locktime_heat>cool;Sperrzeit Heizung > Kühlung;MS;50;B509;4;0E8501;1;-;sd;1;bcd;1.000;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;cir2;min_diff;min Diff VL / RT;MS;50;B509;4;0E8B01;1;-;sd;1;d1c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;cir2;holiday_cooling;Kühlen im Ferienbetrieb;MS;50;B509;4;0E9501;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +set;cir2;heat_pump_pause;Heizkreispumpe in Pausen;MS;50;B509;4;0EE101;1;-;sd;1;d1b;1.000;%;-;%;;;;;;;;;;;;;;;;;;;;;;;; +#Boiler;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +set;hw;mode;WW/ Betriebsmodus;MS;25;B509;4;0E2B00;1;-;sd;1;bcd;1.000;-;-;01=Ein 02=Aus 03=Auto;;;;;;;;;;;;;;;;;;;;;;;; +set;hw;temp;WW/ Solltemperatur;MS;25;B509;5;0E8200;1;-;sd;1,2;d2c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;hw;min_temp;WW/ Min. Temperatur;MS;25;B509;5;0E8300;1;-;sd;1,2;d2c;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;hw;legionella_protect;WW/ Legionellenschutz;MS;25;B509;4;0E4000;1;-;sd;1;bcd;1.000;-;-;00=Aus 01=An;;;;;;;;;;;;;;;;;;;;;;;; +set;hw;legionella_wday;WW/ Legionellenschutz Wochentag;MS;25;B509;4;0E7C01;1;-;sd;1;bcd;1.000;-;-;00=Mo 01=Di 02=Mi 03=Do ... ;;;;;;;;;;;;;;;;;;;;;;;; +#set;hw;legionelle_starttime;WW/ Legionellenschutz Startzeit;MS;25;B509;6;0E6700;1;-;sd;1;???;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +#Shortcuts;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +set;short;cir2_party;Quick/ Party-Modus;MS;50;B505;2;0A;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;short;cir2_rt_day;Quick/ Raumsolltemperatur;MS;50;B505;2;01;1;-;sd;1;d1b;1.000;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;short;cir2_mode;Quick/ Heizkreis Betriebsmodus;MS;50;B505;2;02;1;-;sd;1;d1b;1.000;-;-;01=Ein 02=Aus 03=Auto 04=Eco 05=Absenken;;;;;;;;;;;;;;;;;;;;;;;; +#set;short;cir2_curve;Quick/ Heizkurve;MS;50;B505;2;03;1;-;sd;-;???;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;short;party;Quick - Partymodus;MS;50;B505;2;05;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;short;hw_load;Quick - WW Speicherladung;MS;50;B505;2;06;1;-;sd;1;bcd;1.000;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +set;short;cir2_save;Quick/ Sparen bis..;MS;50;B505;2;07;1;-;sd;1;d1c;1.000;-;-;21.5 = 21:30 Uhr;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/old/vaillant_set.ods b/contrib/csv/vaillant/old/vaillant_set.ods new file mode 100644 index 0000000000000000000000000000000000000000..b346275384b62516c7bb77ca3656457a74c4c2f0 GIT binary patch literal 20808 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 LRQ-8u3Ece;A(DLU literal 0 HcmV?d00001 diff --git a/contrib/csv/vaillant/vpm20s.csv b/contrib/csv/vaillant/vpm20s.csv new file mode 100644 index 00000000..c49bbe6a --- /dev/null +++ b/contrib/csv/vaillant/vpm20s.csv @@ -0,0 +1,16 @@ +# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +get;vpm20s;Date;Datum;MS;ED;B509;3;0D2400;1;-;sd;1,2,3;hda;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;Time;Uhrzeit;MS;ED;B509;3;0D2300;1;-;sd;3,2,1;hti;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;Country;Ländercode;MS;ED;B509;3;0D3900;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;YieldDay;Tagesertrag;MS;ED;B509;3;0D3B00;1;-;sd;1,2;uin;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;YieldSum;Gesamtertrag;MS;ED;B509;3;0D5600;1;-;sd;1,2,3,4;ulg;-;kWh;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;SolarNtcFrom;vom Kollektor;MS;ED;B509;3;0D0500;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm20s;SolarNtcTo;zum Kollektor;MS;ED;B509;3;0D0600;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm20s;SolarPower;Solarpumpe Leistung;MS;ED;B509;3;0D1000;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;SolarHours;Solarpumpe Laufzeit;MS;ED;B509;3;0D1B00;1;-;sd;1,2;uin;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;SolarRelay;Solarpumpe Relais;MS;ED;B509;3;0D0F00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;BufferNtcFrom;vom Speicher;MS;ED;B509;3;0D0800;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm20s;BufferNtcTo;zum Speicher;MS;ED;B509;3;0D0700;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm20s;BufferPower;Speicherpumpe Leistung;MS;ED;B509;3;0D1100;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;BufferHours;Speicherpumpe Laufzeit;MS;ED;B509;3;0D4C00;1;-;sd;1,2;uin;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm20s;BufferFlow;Speicherpumpe Volumenstrom;MS;ED;B509;3;0D2E00;1;-;sd;1,2;uin;-;ml/min;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/vpm20s.ods b/contrib/csv/vaillant/vpm20s.ods new file mode 100644 index 0000000000000000000000000000000000000000..e33d3f52eadf1308af0852f47d401621f81558af GIT binary patch literal 14451 zcmdVBb9kn`);C;hYHQj~F?Bn&?Wv8aZQHhOdurRB+O}=uyL#{E-g`g$d-r>M|9&$s3YcvAC#^hM@FEfr z&}YO1@Ki8%u+X*CF)_EJwf{RwV{K^^A|oXN2ZId*C;}%YDkukdCIA5e13`fRQcSpc z>Oeq9Sz>~G3eM?g86GkUb2x*vA*qQwxgMaPTf zLWPE&u5N?X23|B6))&p^v$fU-0O_RFMu!KmSi58zv)Mw0$6-zoI*mH!KZ@+_?HL#v z^7AP4;aE0xyBuF#T|pw?3Ho|G-`Zqi>kW!`1_uX^jEr1fS~I#DUmYJGKi{97klkHg zip6~oImoI#x$S>_x*7A@-fGt$j@>jULeqS9IG#1x8Hiv#T&&(nWiqqgla9Ss)q~vfs#f;2y-VVv$FF+u@ec6qZo^+1HWkVh;b_pgyr&inj zaVLW3qCXIh_4M?#py^iLo1aQdN(#w>o7vPoE=nnN=(O480}zwtN(09v; z^i>P2_#h76{TUr?+w}b+BkTF`_HcN3$mMnqMtoORMuo(tudl!AcF_(jR!c`nL}Z}J zHzrCMdBS41FJVsyXz2B_S>@a7&BUKXYH=wk$IOMy1$c&Bk zEj4!r;rj<4=R2)Fy$iq~_4(QEbg}*?i55Y@^m(@cfzvaZ`S@<7!2)Ob%dHipNA-xwXYzgitFl4vw= z)fOeM2l2f)UruXzUN3votU8`1cs@Aq7xf$*8~`bI2Cl;p6w-C44G-322BYzT2pno* zGvm8~7)eeLeo!=xL4`c!s29|vG)9*S&Lww|;5PZJ4; zt8{w4^&;@RE@*kZJ)cxIt~svEm;XY_&CZL`YObrZf4)7+6OIUtiW(&UtyJE!9ZHGV zP9Splu;#R}HO8{;40@C;&gOc1h-1|@zHA)sP_L8)Ov&xk#H7B?paC6OH9nV%8MOy9W6qUDF?ue$sXj-5MHQcZI zS-Fq$<0gxQwu|xCTAlDY9L)i>g~w&RJj{#Y$2&A~4pb$Oe{GtaNQdum93d}~Nd5s_ z#F#=J4^RV@wxGrhPq&#u$w_Hc;J4JeI!0Nt_^Bvl6Y+LWvW6;;{u71?&Y2v6p!c_z zi?!B;PC?oB$%Lc^BWGvlWXN8I8i-~BkG9Z{IlkuA)z#Nmcih3gK7zpBmn3yt=yzNm zPtH28lk!GDZ;|SP;+LsZgRtdp3E5q*SaoW+>?K?i=~I8%(+a68(CjRcFQQSY0)qP! z#q;j`a@LsF+?!@BCC&3@uOP{@JYiPRydTMN9^LM8ORouNHo1IZ_FJ778xav`#4(_w zxvV#N{WB3bFM&KQ6;R#%?=OE>cKGgc2Wo9{%+1X?2lM~f{Us;o%VP7o6@a_-7m=lQgk zqz${iP152k((ZX^oSpSGA9fM}R&FFbN8ojwm9O1X>NQCy4E=1qy|t+cQ+obpf`^BO zro!%Eyu32*2z2>9?690*Q-GAA7^8%`e9()IQy8qrZdOPfy?Fbyvkr*lJq&1RsaE@= zz<}&Zi};>u(aQuY=T<8fG}hpw0Nj7n3(0)3iVt`6QhP$z8Cf;`9zW%c5 z0Mpd{1R|S6CZ{THSQX?j;k+PRCbPwI^fv*SG!$gyXnp{8Sy)h;K1F`z$gZYRlahkB z^j%$5*AESYz9+u$7Fgl&`;l01UsGF~<@s!Kn3SFl`!y=4|F4NW(f9(5^`R{NtVkNoQDxOl}=Q&YKq zMAE1`srpk82zcT98mj_z1Q%H(ZqZ)v6MnCD`H+9ew?PD_tS_)L(V-sHc@wE%=uWfd z{DSB#>F1QU5CG}8#Kgj9r^^&QIEqo12@R z4HUsgnPw}z;+4YV<*BPncq=f067z^mkjS2X65Jjs$<4u40X_ozrl(T>k|r z-=$d2#)ghibe6xmE)nY`p5b<9-Rr}HUl|Jm&glwHtft-cKX(E$L zQBl#>0YAiJ1S>Yzpl|YCOK|%j-7Zq)zRy^{ICgT_vjULiE2Q?xqaR+57u75|kU}z* z(F8CF$Hc^3Yl(9grf;Ryg=1d7hi!3r4qwOMP7z;m?S-c!^}dH;?1p3BYqb#=_5C%F ziWg}6-oHGj1nZA;znI(GPZgo@!E2}=be3s#;$_qf$B`0==wk#U7xy{5|C!7Yuxh_k z%I9%BUHn7SI!ezw;OR2%xt_hl{sG>2v_F={13>2fFbo8I?$vY!Kf8%nGEXv_j1Ler z8-{N~fZ5Szu@kXZ?&+-fl+I_etN~O{N!*t??WItVEJ|~XSM{8 z3zZ>^uky_+k}+BmDf5y~Ml zB$%3+&CJZ~y?)Qf=^QuoPt_CzGvA zpiwFf*^M3jt~WP+p+#rtzci1hI>6^+?wuK=d&gO)x7ijHhXEju&{^~A^&i=3mz(`9 zr^DG26yN6oM{$Otjp-~B%)crey2bTjJekcGXw((FrOO1`1h?pn{; za4Xs`K@t<-j$%>RE|}vFfSalhew@22jvcVOXOojo6?CJ-Ucq|bw^Jyopws*mkIUe(%CN+=9J0sNjD3JXSB7j&>Nlci6 zyw@`Beg9%HJ9rU}GJ8_g=hZC|{FIxQhm_3y{1vW4ilV!E(n(B0Lh}8)=ljzE zZTqd<4U5whT+%abZXsb_Xef-J54sz;OO9hMFfVVwEz&@;Qx^p#B}&NQ58jo6_b;Ka zvNnXNGJ@nyaijMzAX=-YO~WI9{@8?WrOXpMb@lWI3%))YfJC~zVN7|Z%EuXPRS4yU z;=os%sH>-Mag{?S88O?;ZaaPmX;&*xQst5RDgbIjsComhl54R52B=4(m>8f2jn@Fk zwDz`)aUN^~O)QQ{?E*Ay(JLq7`7y%=1Ym#MJ(pm20v2a9Q+a%l6!i4d+@2v|=XVoo zkTiD_i17Od2VshOrN4h8nV_PfF*ThiDk#LW7HD;PQZI*dGd9ig2)saV8N8$b7Hj); z-CJV1%a~Gpag)F$AN&}XbwZm)db6q zaFApgY<~}XtSc5j1t99imFJ>I%-iizR&_@B_X;Ew+pTtC=$BIe)rsl7q#jS-Jw(q ztQ>uA*%gm+z-U1SFzJ66ubl+Y{LjE+yVBZatO8I2%p+AtGT{wUfEc*AJl5M>`uqFu z&%Ua4Q;gKTVeE98z)p6QmBDJj-iRb5Bpj;cVT3LW-0x?1gwk7l2zj>vmM9ziqPS^6 z6`Pr?_J@c+Zyz?i@|++ts8G7F)%zj$%1cXQzdUVzwbRr^Gf3w!9K|%bCFqi=|D*>f zo^(JKZ1ZB0Ww(X@cchCQCJv4jZs4+RMfb}{mv8uWS@(+ZHZ(n|Cb!x7rAo4eXPuat zo5*KIE-p{kdw*>95_2e#@lm=?e?MZbe|chT2(8hfcU36Qm00ltHr{OnOyu`i)J0Q6 zlW2J*(AxWo?lPM0sx-TH=gkMq$(2ioNE|cdJ^;a0lC0 zjHeckidBqX^2&h&0OsEk-hU6<|4ml=!S9AAOreTz19a}&6Juj zcve}~@M8}QRaw@t{;z_D0N@625dNQ8)^xB_Mk`?9?EQ;_`dMe4ucEWYKOSr6or^j3 zFtjhUq}fd{mA~JTl&U`8{)PMi3m$+JlRUL$V}7hbBQ?XwjW0&~^)9#R-}Z5oUyR^d z#P?+-nyRS;lGUE&!9G7F*1Pnn?u+T(f0Jn0a{L%=V~%QmL#0XefQqxM@-pl{&CTI4 z!0O4zskon@`Y2BjOA(<{4g7Hg0ZH zKw?5tf))JQzW?wBK|w+NB=OBa(*^v3C_f+oM_K2@6 z7?9}a3j&L@33?;Ah_RAj^Va-QTF%l~jmK7@ZoI$2p#bhW@SaQ7Zdav5-%3wRelq$FMr1Nm0Y`Fo|fX_yp zjsLQLY{AN0UM4y+jof|Mx)85-vR+w@D8d{F;ioMKYVaUe2Kt1Il%p`a@)|{u1#;eH z6a#mSVjJKD`@FA4yQ&WB1v$0KVcMekD9(Y#ec(qB6#PYbk}KbL>Pm9CEM}{Jz6cXG zufa{51VcjDTP|cL=aO7pZxWP4gqMAnNMM6j6{4ds6WO~y+GgZAp6J_-SFCP&n@A>} z0QVBZMa%`6KxI6XcMz~}uDFKtp=VUh7eZWmpLB#N>Bz1uwN5*kRIC=OkBQ5P+s-Yh zI)5B{lxUZh^QEOU+qvcLR56l0{#Ek)j1HmK6HU^d+ zJOhpDsQ>Z`^|br`IGHCKmeX5fAs_mU;HOX(BAy60eUq0Oar=7woxHr6{AHX}yre;A z(=BVbt~qF;v%i^_1|r-?&?0l6u5YOVeHgc2HL55~qmj1@e_IAWgI~Di=|NW1f&8VL zffKL~ghdAdxk^2-a@zy<|ud96HR!14si_cbmJelqK#o_7>6108$ zCFqQIh_|gftJ&pHW;3;>O~!XY6<1svy8NtQgs4Pkq;@Eaxw3N&6ppJa_Thps6mlrI z8;Rg8nw1btB(;PwIGmvCgf6HI9!#`TZ9d=6n@F!i_|2OS&r0H$qMVk*G`(KNKWHr) zj ztbYa5Wp5@$wxaWZfsvX*We8cr$7=f(mMgX9oNUQ@j!`S72<~9gh$I-<&{JV$!*F8${W+Bb z)!Xj8UnvJ&l5p+u7^4~3cVJI-#@R(U;k*TW)w$BSS)4@0v(&@~PV5snJ6^b26F6Zw zGj`d#L^j$aTA2P!cTwYf=I0*^F*d{JIYTBa$9FCYJ6+%)%qiw>+4$N|PR~bX{=V}- zjy>j^I2~|ng{QD6{hL zP&JR(-~h@g|l0akEj>C612FSA`iS zvBPEUD~?v2KcL0TMSVfN6EhBuKyQIv=RB%G@&#jR$l|^W^34wie2sa0vK|leyYS9- zxat+y%v#kO;Y8MSJeB`#=PMA@q{-TT`f7VKh3V+&{1EhoKE)XxueC1(6xX)*+c%6( zX~DDTh?&-;jO0K)-{ir8Z!kY_?2IG`acRsVZVCp)w2sgQ@ZUz};(DHzad|FF6AYI4 zHSCq!5Av-$8pNmCObt|(FqyPG_)C>MwL9p(^&Ip0H#G)scR%!4C1qe8Of51V+&mq% zIsH7GtrN+MNm(5O;!tfSEA*5bagaFGTf$;ElV4F!g!>_)cr{$(BC3PCs-w2V7@S9{ z89`>48;n^&Y*-(7?Ev%IlBHz0@K)D1Iu1KE!YK}eQ8I1!TfX36{{$j<;^!*|BTrb` zaMVPWQd=(HT!;RWZwc~4hGz8MV*VMoMmd$Etr7eR*zu)u+q&|M1nmylY0<0)aLsgnsF z!MjhAXFBncX8>v-qPa2ah)3D+J2j!q4fvSmlirccxLs}$I~?-?C9D*q(?>}FExI}L11)(W$Nfq zoF6t0Tw03jbcL*_plEhUV_XC5`}g}iF1lBuZBDik{0%vIJUPKtJe3LJv`UBET7=h4 zM7}5O{xm6%uyvHLw6|t$UzI8(&_tuccQ)B13{%q37i336RK9Z#iY^boCcRRHcYSl5 zUjlKYhwLvs801@2ogdX=B;*s3XbxH$_7A@REbqfPsFKNt30gE8n#i~x)SGpeirO_7 zppjqMSXZhXR(c)Rd430#FQ7NPmv9xEGVTHID4`;zB|_8Fhf|${uO6+ zV4-u8c@N>|x)?~kTz;;OSszrsQ8~=AVmeW>)?Ee9s@CvBhF%Nwd&RD7LE~;e)_oxZ z4YeI}eE2dvtKlL6(gVmY&eL-GKok6Vtk4d4Q~Auh@htXvEcl*5)5LPm*py)=6)gl| z(%@|HBr1;h6eC~t!~#SDj!aASwky^3)DFl*E>jAS>((q(Fs0gcN%uu2zhom$?AX^G z@=e+X1BcK6^cCfr98!ly2`%;S8C6-s>rk@Ie2MOh?4GJeCCVtcLl1>H-J%kE70Z2Y zD$F!B+~M?(+vwM-h7>=iGY~)nF3aY)f(duLmpO=cz-7Z0f|C$DWS@n zS`@DmHg_^nB`lsUSiWhY+EGBtDxen{ZzNCnRXY%hh;mg4+P9t}{fFKm!^72I{O3|( z|M@C$MqMtI1lJum_1bC4k;2)qnOQ1^6)|@anLc@{9xS6{t+_MLHX3eocTDSOA(Ixp z^d_zuvFSHE3thY^##UhNz3rGi_gY2rO4UNKcGuJKj2n2;VZoc_S#a^D}x`Sh{`k+C?|nZyF#L>CbBQeKby}n&)+TsaA$ZTW$Rj9NXL#k@~`@L`h>m_Ah9rNwEF4}-IQS`==XP{=|Hi&0`n*po@%xu}Z?&s|{VH}`pG%e%(}(qgT1fr3(1s6T^t2Mw1c9^5%LA0*B=02v&ejdcnkI@}n%|8y2a!L^yh744*po>*Ydemp8wPeX zXr&s_n*IoOwLMA8ac>A^vIOf>POz#LQEtg7GG#$StVrcIrn6|(YPDjpH7W!nyzYKZ zuI+=TZr*`82UdOY&B*GQlc+TlFNu;xXD${^>ZgKLnetYjq|2{8TL!K+I9t09hLeFW zb(?b8a@wg_OPP*RBL1gu(}o3Fgv(K8}n zv)!NHHgdvB1k}NiG3`kY$FW;#SwPmHTWYJOmMB2=j381`7>f*3YsG#Myx(GYeZ*^} zIRwGq7snt z%6KcHZq|p!1&md{f-|66M|%?hKM(*z8W8~VfmDcfHMTdtIT~bF5?q@Qf~M6X>1Wf> zBjR!UJ+F3;wtVN#)oQwlL8eAMXBDC@3>H))Ke zFK{QSE*V~C}h!v*9~Sshd@XwbB$at6CM9WhTv41;R)r78*YOfiu)UOE4|2ZjGt@2BnTPNy@ z)nC9V+RZe^Z5chi->=p=01TFKf8F^}0E@{ic?f#2sI)OaWPD*9HNY zVrc|LK$1US!ug%ekeRDk6C29b8scO@wzyU!%^TK>>#IX*I!!_{C-`>|MVL~BZnli5 z?4NuIJ(?wWskew(gBNZ?mqup1xbx`1SNgsVZg!9CJ(&#hSN8b%-$Vt#r>&txnzo=G zG9Re6pq!8(akthx5jLTmYQewA4G>9VIqAc&_Q1Iu`0Qppx3R%~wpYy{BL3Z9l;%Gm|;TKer;dLj7e9J*!V0ROVk8V|gU9F`DO@Q@NC2j7E!0a#Mj z@0}vVPe4|*-;E+$fG=o%GG{G|H^>(r{A+0#Je)g&j1D4V9)a*&$drRbuDXr&PYuRp z#tzf{-^&3OOK%>@J3`zZxpbK(zh7)$hWE92D~=D(gf~wya%!o~X8V?CkE&ZaTKqdXHWe46`lEI2!n+@Hl^Sld$?G0G=>aro+n}_}C zAXorPMwY_}UxjStC#~}b^dUIq-pSU)i6%MIm&^vZ(}f5vNOZ2oYcnuF-S{3sJimVL z+}s<}D_YQTn`t-|wqnLlYxjPmhFAdpY``+&qeJp5h=ud%ExWmuFEiM^8IC$14oEvM z4oD|_yjC_`REB2IndD?(m#2jvrE%|qQ03Xrv10@`qXS4Ain6xB*93#s8q$R>1f>3O z7h?UCBMo9tqVLDK)}c%Le@K5T(Qq_2@&ppQ!-|etRvKa6to(jxY+PE9u@)>!F1mx= zZK)ajBlYZ{Uc|G!v-i;vTHIOu*BT~|?#i78!VSZYhCtJiHNwUaTbOL(W24DUT_MYP z(J5k9P7Xe!EU@Zv00Gqwnc$p_Ev(=yB`xrmtt#fAy89dyN}wQ3T%MLj8`1gBahy2r z)0~?6BhBviL+c0Vr^V!INV@U_a55?B0RLYsroYZP8QAN5noALJ(pG6dFb6JPP>0UY zULi$;g^Fhd>II4<)hO=JkzOp0#};GgNM7z45U1<@=!oEb;PFhDrCpyd9v;G}|1MJ{ zN<~EVK~kcq)ygXx6Hw1?Jr+07(u@b9DL=&i!EM>KAX}B1C@pR_%hqeLR+^aB;*;ps zeFi*gzLms?@ArMLIN_;XxN;qzb--hT)FV};anQbAZOg_%xPa9zX#6N97Q`>`TTVY? zj?gYFY%x_qk9Y(Gf`LhcUQ0Acmy~_(%X}<3eLPb}!@aZ|G z+-o_)ijfBXe#?-A@P@^hIVKXS5{H54>HFz>!@lLliG}*A+mw-VFz-tvWD~xvqKU*4 zVI;pMktY`8VdS2yuc}X1o0RYL;yeqUSQ6hj3tk1>8AEya1%AoiL-QP=v_XP)TWH)B zJHmHF_3lvRh^1Doh#0i&+&8P3W2o8#na1TvAzF6D`#X5W<+s5;7>S&F7P_*yG&BRu$5zM;%%eTub~e10Sc7zjuf z^#5iEf1V?=vv)B!_{+7pr*RUw!i@gjDXl}s7X$QrYAiE+4GS`iI#eSYI+S?r12-hG zK0(kYc5vr?^he;(!_JvZZhB{Mp)0G67uSuQ5(E?%YW2RuA9(cW<5Cf#LC>D}Q_V9iipNd~@q2UV{5= zAt(?`T4XmLLd^XPbc17X9E$dye89Lp%D|JrW1u=Sh^YddJ2J|S+7m~btFWCTTqj9!$&+Q9$jq$ zrtY?FN6jmN(Fd@ID){?t`*L*I_Bwz?=W#!{jk83FUKWb9?wfji4prhCbSZG$VyaTf z9h!OgixCqXMg1~D%#NQG#J!S=8zXjqosu9X4V?+w;ygO)*r3j0MNDF0=g4e*32>K+ zD4A9tXMpR4+R8`NC&@ewb{Hj8SP{X0b65wfCdV8S#!-R?V4Z>6cg zhO+H7l=h}BVmScFz;^nG0>qXDi=i=4OCm8y3G$g>e8xuM?*nrW+0Tc-_L}Sh(7B=3 z;H<@dgD!!mf${o=xPLqr;?~HB#R6^RTwzI$lafB^Wi;x;-UNDiavO>lk>htTGtdOj zuYWtqJ=(}hi82lEbeAx?Hs`N&Caxbh(qJP<)$atMRcQa=LvwWCT#?k*_h_Dtoe7TM z=0{h;=P~u8eMD1enbnx-673|oRuPxPG zla8u?YSexYwxJ2+&U6jE9I{_HZJyLN*Kdqcy_{B}NUuCcp9>-H%xaWv_y&ZL**!oe~1d&Klo4*#mf* zi!SpEL1B2EHFJHw^V;c=!^wS{r3Nc?I1Yi5v^NxL55{onZWNWb`{SIkyvd~)e`!l$ zbPLMetgNd0T$Jjbq>^_ZqK<8`0cjV@4%hD}aFwUCGFUn#>TjZ7WnjA7=LA=cu!*2~ zW3%-6Vh>BQ?Wou>J?+^M<<~8!IC5EM!RIY!Hx^dkqoDy1^+aH?WQZG z#P+$CAD2xbx5#8N^6P(;&f31q#c*I33K)m(9>S@EbRSX?RaGC6_^^D@<3 z_4)nG0y+MRhVbWjDB2R*}Y*Zuym@p=JBDO?ZFZo|sUYBiKEWqda}*fIucMdxuLg!xB1Duw9BJ zcET#_<=fee>^_3>*$hNMn%tk>$D$v=bw7ioBpb|%x9xkkvtD`DI*z<5^3;n;on&I* z*mIvX%GxYkT#1GFq9Rawd^%@aU2roL>>aTX+nOP_`0 z7hKNSfA+{uh+skm9X*8Q#VK(lNoeE+t||c8j!g*Q%(n|pe&rk}i_j%JyG>`U4%;1N zF18r=?{v#4YFnWi+emupKyse8RkM_86RHYrkIfzMoxqUKVYVPCCNTaUPnIHR>TEDsX1?w#S z&40yDVlA=97Bx(&8{5 z-9WNL1T7Cz3dj5m42)cQ>F{8-tRxOT6Asja5o&F9;(ocS{jF(Nvpmxp;Ndh_kEd zaKLx9uPiJ`O_vG4a64rA7}t!m!}AcuxQUg1Sa?ZIXPB^1gMa_NsSu_Y;rX+(PR)Js z?(s__cIOQSCdD#1~B{yHw1l%-(NH zuJCW}Y>ULf0x@gWMt(IP$}m_BlXeTkao6GQL8?vqQOrBZ8D;WJR4*frBsep6<8Yo& z7+{eiSG2u!LPe>xIPxgSgH1WuajQa|=55!ScKevZh^Qz=nP)K7W}V3r5*aSB~7j0-GSHP^s+ugj-fwh+~k;_tpmf;HHZ% z9Y(uy2GT<({6nXzB?E7b>Fr*$cFp!+hU4QoqjM z=URWFnU1Xvu&1RK{(oERe;y>T(6KZzG_bR$vDG&miyO1_`+?|x!5LsMzQ{`p4sJ^} z(rlX5#T2LlPJ5k-yxtKRrzD$SdYm=8Qz6W-5m}dZrh_{aR#V)qz^F$~G9qeRe?-aN zO4D4h!oIxNK#8CF^~%(*Ad8~K$&!LiD=~nY1=f6`HkZsf^@dZrjj(%;)kYL{pe_;$ z8ZUz1+E7{6{vmAny9P$5L9RWhfgr|*Hv(E>#NXZzw?#_4 zpCR!^maRMIYP9UnV-S`!N$BLh2HeiM5O9cw$<|Gwc!`hOtS(bF?9HvsUm zvZd8?u(kc4%}7vy6%P4nZUcQ@>G=%*oh=$5S5ioUk6KJhnD(Et1(@jN3gVW%1c++~ zsOT#rlZJ{ptf~sf(9@tYoQ~1jyrYODjkJ;R(uxJ8bEo?+>v|9>7VzCHZbQ3-j@v@q zVGxr8>syN(t|do_bjoki7M79sME?S8w+1)NKEW{r3#laUie42l zH1mWXf#W^a%NG)bhsWb*C$aDO*b7&xC|%38P6%&F^#sNzZcqk}Fc+b^6nk^Q@rb{G zuLX{lPCT@o-!7CqqZqpr$` UgF}24g8}@x11hw|^!fJx09R^w+yDRo literal 0 HcmV?d00001 diff --git a/contrib/csv/vaillant/vpm3035w.csv b/contrib/csv/vaillant/vpm3035w.csv new file mode 100644 index 00000000..9a8e45a0 --- /dev/null +++ b/contrib/csv/vaillant/vpm3035w.csv @@ -0,0 +1,20 @@ +# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +get;vpm3035w;Ntc1Sensor;Ntc1Sensor;MS;0A;B509;3;0D0000;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm3035w;Ntc2Sensor;Ntc2Sensor;MS;0A;B509;3;0D0100;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm3035w;Ntc3Sensor;Ntc3Sensor;MS;0A;B509;3;0D0200;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vpm3035w;Vortex;Wirbel, Bypass?;MS;0A;B509;3;0D0300;1;-;sd;1,2;uin;-;hz;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;CircoPumpPower;Zirkulationspumpe Leistung;MS;0A;B509;3;0D0400;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;PumpDutyCycle;Pumpe Einschaltdauer;MS;0A;B509;3;0D0500;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;MixerPosition;Mischer Position max. 220 Schritte;MS;0A;B509;3;0D0600;1;-;sd;1,2;uin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;ElectricHeater;Elektrische Zusatzheizung;MS;0A;B509;3;0D0800;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;HeatDemand;Heizanforderung;MS;0A;B509;3;0D0900;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;OperatingMode;Betriebsart;MS;0A;B509;3;0D0A00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;TappingSetpointManual;Zapfsollwert manuell;MS;0A;B509;3;0D0B00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;TappingSetpointAuto;Zapfsollwert automatisch;MS;0A;B509;3;0D0C00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;TappingSetpointActual;Zapfsollwert aktuell;MS;0A;B509;3;0D0E00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;LegionellaProtectionDay;Legionellenfunktion Wochentag;MS;0A;B509;3;0D1000;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;LegionellaProtectionTime;Legionellenfunktion Zeitpunkt;MS;0A;B509;3;0D1100;1;-;sd;3,2,1;hti;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;StartParty;Modus Party;MS;0A;B509;3;0D1200;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;StartHoliday;Modus Urlaub;MS;0A;B509;3;0D1300;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;FlowRate;Volumenstrom;MS;0A;B509;3;0D4600;1;-;sd;1,2;d2c;1.0;l/min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vpm3035w;VPMType;1=VPM20/25 2=VPM30/35;MS;0A;B509;3;0D4B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/vpm3035w.ods b/contrib/csv/vaillant/vpm3035w.ods new file mode 100644 index 0000000000000000000000000000000000000000..b5607c137d72205ee2ec0e41ffd40954dd44636b GIT binary patch literal 17230 zcmbWfb9`Q1moOaLXw=xYZQD*7r?G9jvF$cyW81cEvq`=y_cQlAn0MxnZ|8S%9jvvs zmiInKK^hbc4G0Jd2q-fqNI2MvGlC8X2>}<@!739R>VX$EUAn=kBB1(YYLLeYuASe*PSuL%U77!3lo1}=K zid*KnuBQ%q|Er!dGg_U}RfZ6LUElY@+bJcb!L;GJ=mprO&}=#fh>)|1ku)n5=PokGfQ6r{@<5NSgp;?ZVSIOak-q#SL%;t z+1CqGjifXRN@tc%fLpf z>*e+CpyAou>*K44$NkAX2CWv0!`=|1(ZG{PZV)@5G7pcJC@f|JE2ry=^;S=MUOKvq zp&!IZZs!e)9`v$3(o0y}JUm{jjn=G|bAFe>yS$DEGJvc0AK8hCeRN)|bZ&l%1!B{& zsWDOb{Ce~zcfnaTrwbLWF6UZ0bCtTUv-14?!6^f5Jzy2`Iebstt`}=TK|#tTa&$Ks#u>F-Pv*+hDzrAF z*(bo@L8YXmVCe9?t^~bVr;%L-^lHBKAB<;^%cip!boo{4wmw{Lb~+wTY)Am0&k=C$ z<^^4suyA&%Ar|w5Lk9*1dW4JyWA0~`Xtf)4I(^>$Jl`(<(k$5h3a`=O^;|5QK}AJn z$7{bMf(syj7@d`o0gJy;AdaY0AWsY@EiHYk^b$$m@iasnYiw-nbh&_^yJ?2;Vb?bD3$2&vusd87F(@QLBJV1_My)Y)=Ti>6kH?S5E;vRe zrdpTtm6!57`adRTwY5zAk`HipTR+vSOc(W-M7tyF2C^BA#1hD4U+#__ueQ2P$J5`Q z4|DWJ`rF`q%_cI3$+l-pE#FGnN+~Q=O4pllSs;z1tD*GtRo$ zcE6zA5q|(5RS+H%SJwBJDCKt6u-mMK*+Kbt6-p*p&Xr!TIZmqnR6Czn*MB>$>U??w zaEjOa^C46Yp4*ncTo%`F3isi7(gLyQmxoo`?+d@u($b)}X@207EXHeJA=17bIo$an*|m;67`B9>DkgqX-a`0`XWqr)g1n{=PJ z13e7RR&840liUVzUF)q^zdWo0l#nnY?;HRWpa}{}i1yAGDsZ^&y8J;sAI`!<4c7s* zkk_FGx^S+qQ}lfV&ATo??q=ngO~;lxefd33qS-gxCV3xo!C5S3_L??*S^-_sgh(Q5 zaXJR6>f$6)%df6xaEpnHLn;lODkv=t!@&s&6=-XBz1%ooX`rT{NM$mC`3WyV@$vSE zf9HNTEj}%vC;;YQj->!$;{Leqx*Z1rhpC{X6rYj;xoOblTd0Qp`u4af-f1ygJdR`A zcDx@nVL#%7p4IZ{nfYpIKFd(k-?e*at@hivG zj5NLX%`iDb<2Py5z!b5-z?!nJKArlVK2I82S`kn%108$u(rmUHQD1Jy**A5(uKOpF z+@JST6kDF2+;r+t#xprl#}TB;@x>xT%WiIO2cvO9bGjm)IDf)72d&z6zFo9l4jdt2 zVQH4g;p!C7L_`;*^0+fa@p?U7H8*oKqk4b1UqU4fRF;++d?0-D-F}=p;dVNzcD>Y_ z4C;ZyykZdOA;F~lx!lzeaM-0yfbXkG1^hxmh5Qa`WTv8m1|hv>JDm^S9{Uc7ACuh| zUu01IxZ#Ni54GMtVj{%=SLl7+kI}T@LEQp_YiVf- z5VVnz5rW@sZC`Et<{_fS!M|-iy}w>g+iA9-zc3yoF+6N_2W}6nS5*4t%`5?oRXVpT zoyuTb$bjc%`{PX&Bbhrvz0cbV17hod`8ev-Rtx%#JULtWx+UlbtrvG|^G*cy(VJeo z$MyGm=%}n_zaN>U{u6_A44nWQghPuAVepO#Vc`RRYi44iNXWis2im$tC-Np=_fhAs zJJ{F9p(v@Zf{k;_bVnX#80O-YZ9&~M%7Q=@Jzm`X9ybx74jm}qt0YQfFtxe#!eky+ z$mlEp#A`Z+DYHWoxUgJ>eKeZ;52J07dSs{vVI&PvQP(OI7%AB6edj5LF9|Vj4Tcez zoRt+#)SDS$JjEk`#AwcN+va}D#Kg2DKAh|9qHg|qi%l$w=nU7 z%m^fbri4fG^!2c%`<+;6K+<;bZ_ z*kGonQ!fwak%xv>VWK!Qd%q(hBd-UhrW7U;32nsI!l2;u+ES9fv!td8MuvrPxLs}4 z7!6)E+3yZu63p>nT;xXC5oS{2a5|8v1WRA#Zb5_&W3fp1p69insj~eImaB5yVA(?|XD1*0Hn94;W>( zK9KQr)=y;`1dXcIXmzX>-uCDBhk+>sEj>NrwvVZ4@wbe}qLLC~F}v%g;o)JZizch( z0L<7D@@52j-wSd;M+5o&$PE^0`UG-%|NOb^{4l-40ujoN`htr){>=J-+SXoLO2Nd0 zvUtTVDJcncr~XUB{^icXnGy;3CLV^rWDIvLUduiGxY1&k?4zhU4M5PEMc%tgubr!4 zG6W8*Ct=#aZK5jAyCCoI@UR!XZu~bTi?pCLO#jj3Gp}$c7Nk3 zFNoa~6(;izL4`z>zs2m`XsXS)mSMYx2YL4eV9XeQdYsh^mj4MCSmNY@j}Lz3so*tW zU=A#H8#g8;BjdZDQ*IV0tOxj$+Xm)&K5c|&AfU|5=5Tr_hHy_|O5ImERF_nzwTjBCH)nKL1Lx&kT-XxBBO;VgU8bj}!dXeiB26}BUI?L*RCJJZ)c#iRc_QIyd{CMN}g z7Ty~tC^lmY4a+ahx?+K)>#C&$5N+{r=BA%Z!~h;q?xiJylf$dTAszxaoLh1Vr2vb6 zokM+ivp9vYwa3iFG=&7-gW$TP9>J@v4lq9b*&L1~F1(?DTKwsi*T{Q658C$9ru`WQAQT)Q{a#l5I8WXKW)=s& z&~q6H))RO&f^HgaO6|7kdU0^+!GK|d75tkceZ~b}pLSz4JAeZ4MFed~eaj>nW!PNL zSNc(s7C?FikK*vBsGr*f* z?lia50C3Yrj6lwbIviG8l#q5VGra+q75I+0UZNy<0{KdK{J$1>4#hVL6;Yxz_gVd=7gO9C&n8baXb$ zwI-*FRiQPS^WawQ#gPpBfn)+%&!mMRln>g4Wu5bA!S;{{4gg2jJTe{e$@vq6GjL#? zV+HcI_bIY0$ARuPvN(j14h}c*Bhv>qha76KshSS8-=#aaXggx+etz}m^Iup1Q7mqn z)3gw>#H6iyG31KIa7g$aXehTa{b2bb^l7_{r)a?5B+@V)323?Tc%egNVle`pgSGPF_bV

SRJjoC%)h09NBSZitbb(n|%I@&j zwnC@0ivV!gavjxCOl7jr_gfs8lEOj*wIg%0q^{mEr!unEvIBa~?qMIILbfT@hV++$ z90g9eGpzDDWP)QQSiza1f12($4=b=82RJ390IUT-T*Iq2^Bkdbzp_|` zCqZ2RUzD{jqzkSaFQRLSu`PWObEoU-%FfW5K`QiOV&Nj6)sc$!3TIsrpn3{gr}EaT z+p9~ZN}a}o1Y}L4YmG3~+@cw4dR7b)Z2+FN)wzwRD0s;XNar+eFhJof!JUT(w?$&m z$Hd0+YacjLS&)Ho87^>elg(iUdRQ~)w~m(8ciB3L1MDyS1)2>rB_%Y-bkx%qQ=Ouh z`_rGOAe6*nX{<0>Mr{q#4c$)XHkz7P|0Hh!&}AnXDx|D=WDMVaL6~0<-3^WfE~I)` zS6_*hd-<`q6jT!h9<)pOR4{&YJHVyOtK8^EKcl}SP@w<^z7IU$2PP*cKfGRc`aUe1 zr4kxJbU_-C+f5`IUW6b4)o=(w1mRdg(k^aGG*g4=B-xp;)&e?Zstaad^~$Wil}V}n z+ky1pySZH|W;Tzz(o^HeiG#z5hyfG_z!addC|h+0fU8iClmYZw{st^8tUDDJ=_nBq zk%OaSp7!NN`)b4Yk|q4Nu5wuL!x_5vJ0*|3a)I9I6LcsJ^GKnx+m)M}o2TFCH8nL( zKdOHYuu%t!5gJE8YfUpNqYoNmd4PPSY1wMF-v!ttNO)`!EJih5w`}R&Qju64bduRm zGAaZ?rMD|zlZN1pGLi%fklYvrsqYn$(~Yql)pc8(1TjLL4XsAPu1`=3?eS#eXv`&` zIm}ya*14SZaCjf`N4|2gj*aCiD(J!CX-thwr~SM767sX_i1InTDBg3 zv#jNbSHk4B?o&R1eXSR5RX=Q)HljBVHy2ApP0a)-;DUy4laYp77zmQ+d^emG=`;mN z1xuG{B}?VfNOFMInsWq`bkt<@9C$^j>1EiRf%}TJcWJ;=Gnq$7QIkt~C~ywY)P56$ zkX5wU*O7Fk9!wQAoyt-90fl+T-e^1pG`5HAXSLpfe(Tj_+yXwFyDUf#0Y9rWwsf6> z2YV19(*)4U!VKo4$+X(dc7(&%WU&^EBOnalycJ0R3I2cx8p&B%jfRNoK4mO_B31&Pd8P1hV#ecy8 zR1i@Dm#$r6KmkAkw6bZF1dAmWs~!+$`b2^6a6OEbtNvtBp5$Q!^fRhAH_y+u==+zxb?;P?z~WMVsuxD{qt=r^sx}$k-OsiGKt;vGW&){}m?>IKPc(&u0;o+6 z0S2nHFrPYb;4~W6c#=bk*AX^eaP~<8Fb3*|GF*~O<|qfDe+foNICZf^m_io+K_)Az z-!aO8KBfnyZE!{yE`z_28?Rwc5MV4@O7kE`+#DDD0b+r%olpl7pOEl+f7)a+`lT-j zikmgZUN7fNTRrjm=@;lv2J;BsRq(^^NF61m01hf1p3FMkE22z5xHFzLN&6fOr=U%L~~RlF^>+i3@Ky7!-5q= znX_z-=$I`1@0h?*7;QsV)9~ZB0SB3fJ?8np9n-pu^IC3iZ?}h+^%m!Us$VYE>;h7v zj1cw^vfkL=MMZ<{&VD+YfEm@{HkFbAJhaj@fR{avT@4dhymToTqF1>wBtvM0arpb| zxeghF=2-MBf3gdOatU2!Rd1LZvhQXS{ODu(_8 z6f*nf$d9AHhOxx;r6#A3O( z_~ln%q>oEkz<25wA9(b}z<=v&sgWoMI}<%t4%UL|ky2n=F_cRw*!n{=scUX>xan^t zm<-^)k*Pi|u;H*Noy{!`CUe1oT=zJQK|-v00@EoC7YjqfycRXqSQ-FZApyMO^oDYG zV}P$1kSe&VuvlKa5-$kL2QiLrUQP?ZFq*>D_=Y<#QmRVG86(JKUi@t;Q}|z_(6_-{ z_v)jWP@PoZ�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

^6r1I1$4f6QMUWf`Y zce=v-P$UI8t#U{N1tJsiNML=~%@lpU#-CV%C~|AwSZ$=~!8p$-1=<-$#An4j9{Lf3 z9eqKDTAA?fuxI~7gTCBZa?C6T|37WV<40{bJ}k%MP^yl}cL(VKYAJO^k&qRhX@aME zT2n2Te_V7E9P2vnzj`=T6&J;4#sy=T9kG8*=p{JfdrP3+2FO1yzNTk#Pg*M>ypwII zL>PtpNOjh0c`e;P!8T!cUSnXgH;r2o`B7%<`^CquR)bIQF=eF9O8Z?dyZc7Dp>iR; z>OncCV?Jm15-xinym@ghk%S5Vux_psT>hX2N7O$0eYz*q*Qbv{R zZPJPoeaw3Z(fS7#WU$~V#V|EraXclu3?|%gO(9zHEMK2Z&%Mh15K{~Z4b=?q9H#Mm zXR3@!$K{=5jihkcqjfXI^*ezP&ZA=fRov`kYMNNI9M$+ZVZKrn%0rr2QqY%?cO8CH zCGIB!=ZAyj(%nkh{%22wj0toOG8nW4sY?`RY z2)i#V6u1uI%}L?T`ZQ=&`G!4M@?goS_q!5VFuTF$4M%ymulqQ1yX zN3nf#nUJ}i+y1?AW~ikYx9seaT~~jqa{yOUV0{wa$Z~30BTa8eAF{u^w0GMvKM8vI z#f&p21$wrYd0XQrBCdN);F+vKq4D(%{bw|1A~)UC16Yl-j{3hm|Icj@)`m6~rY4R~ zbPmR*;|b$7fec7Nmps8H6H5a0;NT7vBfl+kx>!Rr!0B(&Q8qea64Vq6%TIFVb}Pl0 zH)HBE&JDi~Mb?&ftFRbRl8#82Hyl%QwbK1ATIE_o+gg2sy$vbf*#!seXVfi_iFbUMwAbAKe@ja=s{ z%dLemY*cCwZ6x^NFAxnaGZN$!__ak&x}Q1uR*|zi?|f&_pnWzlpU2>eI%aZdBMh#1 zUvI0u`a&mg(<{l`?Q87 z{sv!Fyy|oK>L1N#zyX0%;QtvokpqTL*w)6>!pzy>uh-Wdndl9Tj7+Rd0GGB7^hVAO z4*#_h3JQp+AwPp>pwAc1Kg++r$NrCd|M(ABVf`OuEvyaAOdRQjES#(j?HmD9{P|-2 z|7&LpIsjQ#R7H?hQcjHizvmVZtyic>+w>A3tskO&Ssj@&Rn6njR5^j30af5}i8Bxw zLn3XWk4cnQEh?WsJ9ynNg3z!==w|mE+9Pt=5#@`7m>SsFUJ8#r_k5*dJME{!bOJ>> zt(%_XD~wzXk5?2Ij$ug$DqKEE1$s4?1~PtY*UL$z+lcln(x6YL-rVA;Z{WwTniszA zkPUIoQg{@o+y-iAro~5f>M7jIV$~U)!}D}Up|N$AlERXa=LY&>8IyQk86?j#k+4%o zi5lZt*lZxCpzQMn7T9qeewb^Ldk79vP1)m1b@b5eGk!FV-*~TJcq|?sf1snxfzMMf ze7UN89p?rSf(^|xn4q-DFL1>9XwBvL+e_{z{6&0yaP&-)p`F5Z(bOUJlR@?BcaYEd z5n48mAplIfDA?!x0E3_b{qJ8d_}3Zx=eG?06YD>}Pw-DH6~O8L_O*h)sr)^`|GN18 zDYO49zF+@+Bh!Ck{%cm}b8-HkWs&gTmg@f#@n2I1fAQ^qV>Z(Ry8B-#p#Q}BSGDt* zR`_R$V*J-6!++xatGxYt2Sa%OT}AyT=4TCmi`1t){;-5r- zfIg-1pXDq6|0Mc9Wb+@4^Y`TaD^q<+=Rb=kfY|?2Ru!bdAwI!i0DoS9-n9vQUj2V& CjT_kj literal 0 HcmV?d00001 diff --git a/contrib/csv/vaillant/vr603.csv b/contrib/csv/vaillant/vr603.csv new file mode 100644 index 00000000..4a220575 --- /dev/null +++ b/contrib/csv/vaillant/vr603.csv @@ -0,0 +1,51 @@ +# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +get;vr603;OutsideTemp24hAvg;Aussentemperatur 24h Mittelwert;MS;52;B509;3;0DBB00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;FlowTempSensor;Vorlauftemperatur Ist;MS;52;B509;3;0D0100;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vr603mk1;OutsideTemp;Aussentemperatur;MS;52;B509;3;0D0600;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vr603mk1;RemoteControlActive;Fernsteuerung aktiv;MS;52;B509;3;0D0A00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;MixerDutyCycle;Mischer Einschaltdauer;MS;52;B509;3;0D0E00;1;-;sd;1;sch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;HolidayActive;Ferienprogramm aktiv;MS;52;B509;3;0D2700;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;OperatingMode;Betriebsart;MS;52;B509;3;0D2B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;FlowTempMin;Vorlaufsollwert MIN;MS;52;B509;3;0D3000;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;FlowTempMax;Vorlaufsollwert MAX;MS;52;B509;3;0D3100;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;DesiredTemp;Solltemperatur;MS;52;B509;3;0D3200;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;DesiredTempLow;Absenktemperatur;MS;52;B509;3;0D3300;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;HeatingCurve;Heizkurve;MS;52;B509;3;0D3500;1;-;sd;1,2;uin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;OutsideTempLimitShutdown;Abschaltgrenze Aussentempertur;MS;52;B509;3;0D3600;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;PreHeatingTimeMax;Voraufheizung MAX;MS;52;B509;3;0D3800;1;-;sd;1;uch;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;FloorScreedDryingDay;Estrichtrocknung Tag;MS;52;B509;3;0D3B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;HeatingCircuitType;Heizkreistyp;MS;52;B509;3;0D3C00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;OperatingModeRemoteControl;Betriebsart Fernsteuerung;MS;52;B509;3;0D3F00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;FlowTempDesired;Vorlauftemperatur Soll;MS;52;B509;3;0D4600;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;TankHeatingActive;Speicherladung aktiv;MS;52;B509;3;0D4700;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;PowerSavingActive;Sparfunktion aktiv;MS;52;B509;3;0D4B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;PartyActive;Partyfunktion aktiv;MS;52;B509;3;0D4E00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;PumpCutOffTime;Pumpe Sperrzeit;MS;52;B509;3;0D4F00;1;-;sd;1;uch;-;min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;PumpState;Pumpe Status;MS;52;B509;3;0D9100;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;CoolingDeltaStart;Kühlung Starttemperturdifferenz;MS;52;B509;3;0DBA00;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;CoolingHysteresisTempMin;Kühlung Hysteresis Vorlauftemperatur MIN;MS;52;B509;3;0DBE00;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk1;CoolingOperatingMode;Kühlung Betriebsart;MS;52;B509;3;0DBF00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;FlowTempSensor;Vorlauftemperatur Ist;MS;53;B509;3;0D0300;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vr603mk2;OutsideTemp;Aussentemperatur;MS;53;B509;3;0D0600;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vr603mk2;RemoteControlActive;Fernsteuerung aktiv;MS;53;B509;3;0D0A00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;MixerDutyCycle;Mischer Einschaltdauer;MS;53;B509;3;0D0F00;1;-;sd;1;sch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;HolidayActive;Ferienprogramm aktiv;MS;53;B509;3;0D2700;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;OperatingMode;Betriebsart;MS;53;B509;3;0D2B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;FlowTempMin;Vorlaufsollwert MIN;MS;53;B509;3;0D3000;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;FlowTempMax;Vorlaufsollwert MAX;MS;53;B509;3;0D3100;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;DesiredTemp;Solltemperatur;MS;53;B509;3;0D3200;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;DesiredTempLow;Absenktemperatur;MS;53;B509;3;0D3300;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;HeatingCurve;Heizkurve;MS;53;B509;3;0D3500;1;-;sd;1,2;uin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;OutsideTempLimitShutdown;Abschaltgrenze Aussentempertur;MS;53;B509;3;0D3600;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;PreHeatingTimeMax;Voraufheizung MAX;MS;53;B509;3;0D3800;1;-;sd;1;uch;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;FloorScreedDryingDay;Estrichtrocknung Tag;MS;53;B509;3;0D3B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;HeatingCircuitType;Heizkreistyp;MS;53;B509;3;0D3C00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;OperatingModeRemoteControl;Betriebsart Fernsteuerung;MS;53;B509;3;0D3F00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;FlowTempDesired;Vorlauftemperatur Soll;MS;53;B509;3;0D4600;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;TankHeatingActive;Speicherladung aktiv;MS;53;B509;3;0D4700;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;PowerSavingActive;Sparfunktion aktiv;MS;53;B509;3;0D4B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;PartyActive;Partyfunktion aktiv;MS;53;B509;3;0D4E00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;PumpCutOffTime;Pumpe Sperrzeit;MS;53;B509;3;0D4F00;1;-;sd;1;uch;-;min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;PumpState;Pumpe Status;MS;53;B509;3;0D9400;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;CoolingDeltaStart;Kühlung Starttemperturdifferenz;MS;53;B509;3;0DBA00;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr603mk2;CoolingOperatingMode;Kühlung Betriebsart;MS;53;B509;3;0DBF00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/vr603.ods b/contrib/csv/vaillant/vr603.ods new file mode 100644 index 0000000000000000000000000000000000000000..84109af18d92c9398051f616b1d2f47fb327b4f7 GIT binary patch literal 20495 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 literal 0 HcmV?d00001 diff --git a/contrib/csv/vaillant/vr903.csv b/contrib/csv/vaillant/vr903.csv new file mode 100644 index 00000000..9b54b112 --- /dev/null +++ b/contrib/csv/vaillant/vr903.csv @@ -0,0 +1,6 @@ +# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +get;vr903;RoomTempAct;Raumisttemperatur;MS;1C;B509;3;0D0000;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vr903;RoomTempActOffset;Raumisttemperatur Offset;MS;1C;B509;3;0D1F00;1;-;sd;1,2;d2c;1.0;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr903;HolidayPeriod;Ferien Zeitraum;MS;1C;B509;3;0D4300;4;start1;sd;1,2,3;hda;-;-;-;Start 1;start2;sd;5,6,4;hda;-;-;-;Start 2;end1;sd;7,8,9;hda;-;-;-;Ende 1;end2;sd;11,12,10;hda;-;-;-;Ende 2 +get;vr903;RoomSetTempHoliday;Ferien Solltemperatur;MS;1C;B509;3;0D2200;1;-;sd;1,2;d2c;1.0;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vr903;LcdContrast;Kontrast Display;MS;1C;B509;3;0D3600;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/vr903.ods b/contrib/csv/vaillant/vr903.ods new file mode 100644 index 0000000000000000000000000000000000000000..a8e68ad95db736d9ac47d07ebfd9747c521cf6b3 GIT binary patch literal 15028 zcmeHuV|-@KvTris#F^N(ZQHhO+Y?)pOl(eU+xEn^ZQp0!efQb8XP=Mv)9L(H)>{2^ z)#}w%|EjL))$&pxpvXW#kU&7p(uqRB)*KPEKtMo$4nP%~u6Rn-SiLJ4nk&BIqtuw8Yy`zbNv6H!piL?B_@YJ56!Qw*!0{U~H z19&Q%yVw}o8dz96(K-M9lGfhVEL>hz3>FF#3eW^rLR?r8aJ~fs0tSNo0=PQfU$g=O zLIIZ$7EpH2IM4J-kx{`Lij|i6agv*eOStcQxm^+F=%ItTC=o5S_v195LS%#q67gqz zR(Md*2nh^hkZ6l=5Tl?c6on_b!oS}5)u+tR@7A{vq@=LSva?F!o*+pXy5muH+^5vueSTR z+%EcEwY9aIBavF&)cDZip=`EIPa%O|xy}SWUQik98X?=V_YO6l)9z?(Uq$7>RRKD>O|; z6I(7?PkVLZ!bsC=nM5jS ztbddF^Yde~=J$T7v zO@DtsK(O0}j6N^UWKc(v|Cgc5>B3J+m0rj;gT9cNnVHI_8&jJwspGrhl{ME!Wr;m zVq^Wb{2}ngU=9S8T>+0^wOwo0@A=})6thNjxHr<*=Iei5Rm*0*^gUNxS{kNtMvIJ$ zEY#P{qCX5#j`w-*?fEvH)dtg06-qXXyZsam{gaZ5PuEzXT)n2zX4Us*glu>@9)`o? zOFEm~AgHFsz~iQ$-ydChD?3xCn>>iQ=H#VPt2|3A85u!J;qh`cG&EFIU8pwb`*oHv zTy zGJUw`k+FuXdsHJisY+ilSiYTg_ghM>m@6@G6;piJY%A5R`8PAaPQ{0l;{<(ol9n3P5-8n0~QrCarFJN?KZk z`Rf9-+5H6DruTL)7&GjT28+3aj>iol6gWKIsHxMcE?zkUhQ4N-Ro3~@Bd#0_6=ISs z7ORCL#h(;Pq9jx)L$P#JST48>hM9n8AdA_dUN~)C*0_ zW&KOnU*xd!blO}W*PP&63AKTz7c~>3Py3c?j8wp8N}fnNPfE*jjD(4Jd2zGJucFyD z!a_p76v<{rT;Meb@izZPe!GNCagZ-7cG%gL8|#HrCMd?&mz&8GF)}i`rm+m7Wb518t0G&HZqQ~z;U}~0js3apL zbv;|U{#~L382A3HRl6>nK-eR!{FrRNk7ocJ*~tg1o}gZ}8m+@8;b*6g7h&gB{s@cx z@y^rz?oPf=HvhBV1Oi0><*H&@x;!VX8W3WCGlgFbO5FG`88;il_m@SsWQ-On#wQW5nbv_i(w#Q<#U2C$_%UC#y zn$NoI`ou+}GkzMxvdfXk^84@z0x#z3>?OGgC(Gi8v^RgXW&r1hI|8@g*xiAqFakZh z=0z{~{5>VLFAOk8Gxw!Xd0*d)dbDBtu(UA-WAVBGFg6^BARtB8224f>2aVzEZR7}mL;+JO|N4&jB_MU~GjDOT&I~>%(iS&f3}t6$=PEpl z{i@o%HdG;+5|}w!PKB75zcG``ZK2SS8}30{)fM1H564pjR}8I#q~?ucd5XH=E)Kz^ z63P9cQ-{1JfAPR}{IaQsqP6F|_Ul;M3*i;DqXKA#+?VxB5u3#-y-g!-aC5lh+1Xj{ zWj)@CjnU(DbRh{BpT#O9L3R7!fsm6H6tFj~DBoS6-x-X9k*OPsboWtdU@Bnu81Cxa zAH7G@ z`gDTC`&|rjAta0i;Th2!@9~koeWTA1dS*ygq+9Mqt`Lbt1wdD?&9!2}n6_&87XOyT z`3~QyXCsi?wrnZdaFyD^ReL^YtMk{4~Q1$<5_Q59G>Ag zZt+Cz&2nKALoWQiY}m zbWi98ej8-h?dhp)^z@X`iIeg#P2R&3um9J$I5_FQS4xXXlqPJN{MV1EF zW*%+CfLo(djLSSGKi*#%XcqWZQ2j|w$ea5D$A5BncyyXgWu+9Itu$B-MqwN%Q#Y?c z{Qx)u^`Zh&VAQsjWPtZ@y;ys0In1hi^IBS@;|%8F9tQaP{I32%e-H?H`Z;IiuhU4E zOEn;BAa|Q59oK+a=n8z_n>)agS70(L-cuOWxm&69l*=_d* zbKX`Pp|)u@Sk{?N2#%;#Xa=(<((0@@BYl3n+VwZuZFVMYK4NgYUjgjqrhu3xt4wS&2CEJhPd!7wMzBxWb=NJDv#}dPNnq;XFaIyI5-xi^UaDD$!b*XeZ|@ zH=RgZZL+IUugQ}PFIuTJfd(f&`UE)a!_&f&A*u0vV^hSX)zzIv3UED!{y*{4NO`OO}ly-=>;BLjQPPi7=J0ww{FS!ND!i zqsA>*$%kc{gO3ak?@7^xm!3Blwt2mueZw6X=hn_yvSj{ZaBNssC4U2mGrYXl`T?F% zR750|gwJsgGN{@4SW(LGuIHe}+hzdB2EbDWw_uPN2hptoDPOdn^C0gHZ4Uwu$l=wh`7h0L*`AvxlxGwI|6P}h=bc83v&J#g&jC}#(tN$ z6!3wep=3%GD5lc>e&H^*$v|DI)H0E@tgM)txYlsQh{)qa2n!@wlOw~{C^;w3T~UC> zhcv@E-k;2;ptzi`+)w8Uq0ws7cg?!Mm{b(-$fUEnjMlpL2iAv&fE)A(Z_d-1yM#iN zKziaB=Zi+?e8sK=I9!*L-!*#5W;KsF?yn;LS!bvg?=SaCN=h!v+#4|n*?>S`WuX31 z41@p~e)b!zo)Fr2I-48?m)w}BUB~?bKdKm^meaf`Z%6(-4z6+7DZaxjp)0^0VzAk2 zN21b9Q?f>$NW;SeUt2Y%Mt<4d*^!QPKAO%&&p4_*wgyZ{%XFl%{C?w#af?eaSD#xQ zv6@fwzbkuWEr8{NAmHvlHB%LFF&4|T$H6X>iqJO z7pbR0&Ol;gqKuJd0q{#cYtW8>W}d%COjT~#CUbhRNj`~WBBZecaV?9Q%|XeI|1Kju zW3x*fi{)?mSP64SP37W6$rBz+MXN4y`CYCKui40z2NwpKk6%2p9&w#B)eO$J_13>H zbDcD?Q#UWoI|#Xl-?~dg{J*@-3~S?g0JI=xcdHh&=`|m*jrRvGaeO#5x43jA1M^~& zu=mWMuA<_sS+-A6R!zTa5Vyk#a*9{3Wh~!^dzEg7=i@~ML~Tq?^ajA*uv-59rPt;A z5L4txMYLS(914K}2?&@Z<>d65?Q@4-b4(o_Ydt}i>3~&fzMz2tf~XdYxgyqDxc2d+ z#FeAy*x1l=B3B0U@698D$|-chG+K@27H0sBQYlnua--fTI38Rse|UXZwWG14ipDna zdpRx+L-B-=n{1e?D2kE@f>slJA63n`ZCQY0S{aB$!{hZ{y17^YXjkfF8Clan(e?lU z>*3FWzb7-ftc<3-n~HmPWYTOiCM@|9r*9f(@d@MPasn_gFphAhVfU4})-5TYPQd10 zepYl|8s76nw9rmU$DWopVyVR9)~9L$0gQ3IekXzo8_0{Vv#CrPbI-%UM7rDAQZ5p? z+r(n@?UUAd^4zK<5ilq!iZEG+GjrCyO<_C} z=C%7PWIfu+&xBjc=UmA;OLWoK&PbJFW%$D!mpF8qUx_wFL%23e@N zM$m8Wsf1DpVX_dai;Egr;RzZG=E!`M+?-y0_IJxjjIk9IRiX5h_o2RpwuX(5jk^CH z_fhIp`)Dnkni}>eN#@Lj4fYTHUYx#;BP0ok*9kJG7lR;~OmgG7i=G zC9O@6&1N}0VPx&jSH#4dXYz!erkH#0m8WQyt+(1k5-P*-VN*8lEaa_We4?t=0MlJD`t5-hrg^3YpX2rg2}JZcd7aJ#=>r0$&PQgg-fQH4S^R*R5@ z_!A@a3Akgt_x3+b;_KT-PKrYoNH@uJ$Q=y3*l*dR46Q+u-2JUSwYOkCy_OdG41rZN zhNxd)27~#3H1U9pBdwhyGcXMwh46j0b7co?<`YsK-5OpI?V&e_GMGS2rwk%0PuoVM zx%wmo=rB!>;%xo!JVHtkbwg;br5h0*o(_~B7ES>6Oy>&`d~mdHez1vnM!?-@E`h}O zh7k4ZYxDQe5Lu$y#%`OBg;-`Q-o9@z7%BB zSSbp0$Mfpt`*!2U!X|kBTu4T-#BPue3Z009Wp97h6alSnP$ZaH-}Go`s@HmHWzzMC zF|7#gEOZsMsnEj1@>`k8(T5$Z5?EhQm4ZNNos)p)iUew7aas3bfb!DHhRL@o2j|Pe z3fYF;l~en`eBor&l5yc=R%KDt2`sj9VYN5~kvVj&p%JY(IJI{Cq)&$tel)?n2k)7^ zHp!Khp0e34d{;zY8t|IGPWQJ0rE{&p94FQ3;DYRTc9bLDFnmEq&d8%M{np0E=-z}X zlG%DqzdqcoH%_X8@|(ntC=A;sSZ8y`aWim^@m*tVwp$7QQ7pRSy-vS0`o0noW)N2C z1pnZSr3h)RY`c_gt{gE1^vPjHJ{lY@lS>Lmil^m1=R|hAaE2aQ)+*S5$34-^p&UGa z<}|k4a^CU;cC6G@X3PsW`aXmsCuF%EJU@gb^OxsXM)DY1i=iAZ@ts2Y3;kle@5n{& zum#)6y+_`lKQyQ{kBkxY~-?d8uTcn5vsv^b1c*@jOE!CY^&xW_H|R<#=xpBq6RpgqR)3eA%az zm%nNSjf!6qnIw{#LXg?Kg3cOR8wk&}ONTls(fNKX|I!7Q-h}pRW!r*B)oPEw3^rSe zp4;ccdjiA7$IS=4nlY=B4Yx}e&NKT~h|Cw-4_D#K?=lHxi|b+FN&zWjMZh-<>5g8K zg4pF=GIg_a?v(|>*JM@BkLv8J>APaOjdh9ZCy^IpQ`pdEUR=mDW3EZHf+forOp1-S zM7L2Gh?_o+v8)k9@n`|f~j%`8-i=%~iYNCEeCzr@gVKd`D=m2aSN zt1}sob8o)kD1&oSR{_{eKZ2exW69nA`et3#n&zOdKPtHPy1qJao~cm!!)$=<+vkrt7)hzXjPm72`qCR-H0<&(6!EPZ0oob=^6zTEqe zW1ocTH?u~rotV&-DA*@nA@9%i#6_5vp>XofG>W>W$F|EwERUV$acL}5Lm@WP;lYqV zo7j#n$uEv8YZAIrYl}LccFhWnb`ZXLxkUX5k#hT{(SsFdExG&+N=rq@^5IyD~s z3#V&&-_KKzV#$fm#GA zg`+Dqz+wrm@Z&{~E;VQ~m$l1R5YcP4hFi5)oIx9eJ*gn9mvEXM>=0nFR;}XDJ5p1^ zo>)aA*SG*eqR~(uAz5zjzVPlTG^HJ!MT`U%gTW%+tBmC)T1}sWRO`vCGsFJgMuu%L zi++*uzDK`?CbNBD&L_7J-N`;`WEo^06YVm|EEGTFhWb-OUQx|K8`bm3BG`;2jr+5u zXYDGSNc84c&tr2xPF~l&mpZT-bA1dF(ok1hSY9(p4g;mot2m?pO08sc+zf2dCMwve`D^R z>-YA=jbowD4rwfP3-QgYgFttTB{;>o*Xr2a?e<7;sE>95Zs^olufRp3f*u zqf;M-gaV7q$830x2xb-aDZ|=jD8mZHI!}C?826F2ciGNjmrE}e5{iiLLq)%RR2x}; zetJBS^$B?Mm-XCX{=sZ=PMVD{%&jKrQ}Xr1>>vw~%P=)sMi)lta>SlKfmHh9p;&bk zU!4cJ&TQeSWe}zFDeFTr5hMJ*#%cY$iX|}NF#40eh^;F{S!Fi51Y=RmC zHGN^Fq9+}#p<@X*69t1sYVd>WVS#arnc%biEgUPu60h+M#?(DmaU7aKAYZV0(dTd2 zgZ0UmcSEnr@az4bSMO~x)?JKhbXDW)9#}$#USSM0-=AVo>BHzYt&2gBvnLvIM`H0f zbDkcqAM)YYJAEr+4VAG5qFv^?Fn)_UYG94L^Z}n3rT!l5&GW+14+^7%B!sd@I2iTJ zhg0A4p%MYMQO6pGS**-Q5($5-Ut8WVe2JVMuJ`8yO0dG0W-bkg$TZ!gpZ}d4FUuMPzXWe3AdUn4uS`AuT+)Z)s25P=eu ze!n{&tAHaf*TXV78d9*!>#Id^9}%%Z=)igw*Rgq@;tqIXO?j$3=YxIPPkFRF z6?if6!GC{AEsgML^sTR*q)aQcg<5JtDR29LB|2@-qr(o5`FwX9NO8}Q88c4=-9)*F zhO+Lq?^ezLW&R3vkD}<%SL*drgQgi26v1mxyiUbG)L?U ztolvXh#kbz4gBrYda$%~TRg{AE&xYmX^S5cqW1+t@N}*QE=aWmB)4#YHebJLj`%uo zPQS0XCmGMk&!(}n(=Ktiqg+b7b0x$3U6gxKKyH)XB|Ly#6>pl%9~2@JZ)sn7PoLBJ zInGX?lLZ@_Y7;YQv?&BC&*Pm9rXLShp5fk#y{$A`B$Gu;P>WqWlKUjbJC{7tQl-(E zDs^4Kp;Tedgz}=9;`?m*WAr5LB&BHU;&o?U(?(O=<3tv=!&dt-&)$u-wUhmiGCE($=Hz zmMV5FBv}x#Jc9EgRi#p0@NO+zv}kMl0d3m$$pNZrjR_$nT=319; z8yNk>>nz{9l}oCipSX?Xq=Bq2gjj#&y`Jq5+b8o(-BlTO_|Bx>u_1zE2h`XUcMf&u zp-4;z^Xvt`Ne4tJm#nr|@#Rhora)wncjJSX*Ri|IL{dLORJsO=R}*JP5W2!=IO^S? zj;S%7Pj$+Y9nGexvwL&n2aErE_s3j=sm=r1fnhRPv8+8@Ly0;;2VBYXmyYkcB*!kE z>A=%v0-gfzH+#nok6FT#I>DUtlZzD7c#3sk0bLXULT{j+z<{>=bUA7|oIYyeyLO0g&4_3{#xqvfj*ii^vtv`2$WId zG7<`Lp&Sfp22uV!w1nU$JFsNObpf=b-`!L&*}Ad)vwIZdYwA&y1jp6wouYAi6Czu4gd24Q?0D zhSjvI64`EFo4`}ZBe1)GHH4>mSziHL_mexzCKduV&<86lZNSM>z!vh&lA;Tr?QcYJ zSYKWnU@POWI%zyn%q%;$-Rar)FuD%1p~kWqR%>z9Cil>v7z$Dtl0m6eIs*Ik`i1q7 z#~D^P*OsFk*E`x?5#qK+$PnAwbo9qBZFx7=3pc%o5HpRk?wI0shcT+!uHCY-{i=(~ z{5o~Y_cQm#I-^rh9cpG@!<_stTgNPd78!$D*|)-=_X0R;Xc?{i8bO`ze^yFUqj5+Z zt}$;Q9a`Lu61eU~)&z%u(0+7&^8K0Q2PG|kF9*!w5x{`|he`flAHbP78~mB!M<-0g zq|+k@Kl(uJO`=*G1q6tomqb>IS{4>5x*^tF7T8APESrjNb{^2ltWdY^J#l3?Rpt72 zI&*q}9R6hC5@rhcM&B!GBFlB>^2xBCcX*&R0i=N;dzh0sqbLuc3=OlBx z@qW~4&UMQJVJ)kt9MxCqmcm?>Rx>r5>y9UgX~-Qt#9BYqg-p7vw0G_}LegP>vSSX3 z1PmP3C}4;=-`!*=Z96T1G+- zGd)d1b8)`1z{En+SQ8w~(oH<33$G5?XSq!K+d^Wp^6k~7-F!Q|Jo}PeQ68H_kxwS`A4GJvhaf$ zz(7D!ApcX?_UGF|Cua|9lfUv{`#PsF`Ru44U2=#s6$(xD$V~;5Bg%#KD;x8b%_Ir)km7}me2*RvB@Yq{tjYY{Ti=nyTZ>tkYGTiwo+q!b!Q8!lZ`VesV2B`| z<$kypOClYm4?B9lO1zxEZtl0-wZF^}X;$GN(b5>(@*E90B46sD%h((7X_Eewn`OOA zh7^{qzw?L4H?gKw0D3QK|B8g>-F? z{z|i8QS*#>&FUMe?GbH^@S>(<0{A#YB#Vpt<@ZZlb( zItR8oU8tN?!jJZ&hft(#E-`8$kYQ^-b{bXVrfCBjrbPwBP`<_zp%*ei-{C9mGbd#u z#rEm^f#_n{gnV5KFag^nxdR4e$N)S_A7$e`f4jkwTc!8l&pW+rKaMTRJNF^NdJ>h? zTqOI*RC%;jq98|AiNOA4ini8L*`IrE{+^5CozR)+Az+Sm@oS)!saDt?E|PuDX#o_* zPm=iA3ZcU0rc+ELLBLSE8SyNB)qN{7PHOA@S!1p$is|tyxhC^J3|(Qs+Gt!cpXdGC z+zQnf%0Ghz!y~TCYW#~RgGk+g%Qu9oVb8re)$=RtNNkhIK{~yt4YL7R^k8E1Uk*O-cx!ncCZ-}eh}gfDNN6ck4Y zog%2L_0H0jq&iuMjlnt68{5-jV`{}0Sa_*d@(^7tIjAvd3y&W%#_d}6u#L89M#enF z+=_3bq|Q1NMDYBOX9%EJ9FPnFeM>#z5{khk4s_&kG-MI}a*oI_>8Zy!$Rg7!HsTm2 zDNfNzv{&ae)eaS47XINl_;3t@3+tm3eh)eu_Mx1vPUG5#4FEvl48OMcgcrOwYx*pgXh#kt~-!a z*>K8pW*ea`utFJr7pEb!zeDxrr6bh#4D;jmXyBUUOON$0JMh_di>zy+8uc6IKR<3a zGaB+`ZzjL0t0rVbeUvBT?yg>cr-Gmr#7E0cGc)hPFgZR`N>;l#I=_vu{^DPks9@IbGQi~S2 z4iJ;m&HfhQs!wOhab4h-cotzId9k}&6pbgQ6^12FLTIBKb>&kLN%M44T~yvCIE(-m zgk6Kc_tg9D3?Fs)C5)DkIzxtWK{7NK`^n(ZrAHK`d zh7gul0un{-@S7W9HYeqM)eFOz&n^nSY7ict)biJ>33s_$qnOIIhf3zoN=@xJ^qj2# zh>GhJxkb^P@9ezc0mMlbZ@A>Dy0&QCF6u?_CoA&2;sjKK5EP1_PxuY|Zg?5d#8Thb zsPy9}j{=O4lNUh-LNg@OD6F&Q%>tjFq%&ftK%bw=lVcw@P?4J85JFxCP}p14J%;x7 zcZzNX^ldv44iBIOY&*?eZkMk0D+r@|F}^i!vxX>`DoQ>Pw+uJM!nTw{NP&JmEr&~l zqQgGJ$p8;rU=x5b*&91T39(9E(^Cgwqty2ZY&7T}Izumw}#J5Ot-ID4@!h0jZ`0gmbL`SSPv z(rdvB>w>Rt!H-C^kG?NjWBVJtY$;}Ho_0q+UiO_DQ1!92*-~g~pEb^dEOga)f~xU7g4l%F+qxP@E9 zM;jxnd9Kaq9F6Iy1UJmWcUFb*_(j02exe}CknsHO8)!LNPrQx%dd643M{TU{Hfg4K zoS#dO+!h=(tfU)+>dzZZGp5K74SkXR_w5O8Y8_ET+A*H3x?%iV%6pZubE=lcU^e6|iZjU8aE(u5kVTQ=z{Sv} zW`Ix6QtGSP#OFc?pwBpBJT6~!u??N4-**t=n=a~eWHz9y$6M$4)hkz1Y>l2JE4LA@ zPb#-z2sgej+NU9CH9>oG!1HvpeAmKXk9G-3C+G(!REwWL8b#pfTJTAAkCtd(@CyGG zu1y$&0FR~tqD$iZQuQgj+;It!DNuXgD)V$3{G(^?(${WwVdNHqEjn~%h)NVuG9)Bs z!%L5!Z@+d@zD{0gbWzHAVJ=}Yek4PNrhJH+t5jrqRnB>Ej+mQU`)p)lyfBEnE!DsN zb1pqqr;S%lW(AsW_Lmplx=ZW0wmWeP!F*T@sW8h9;i$w|VlLsRwy|(3bR_w$FXDi{ z-?kCA#i_^Imq^}_HKQO)#4N9{*t|mzXc&}FsDSufXc*Do@IjzNP?@|vM~TpThcb4e zhd&?lCG13hrPUR%Eh5*qX3*$xo3BU0Xg>A^EchI%iJeBJ-&Y(?=X+f;#_t7DbMpyx zJ)PL4Li^q<_T8J8n+6$B7zfe5ihXAn|1toq>E7){T?= z-H+nX00PGgiBE!VxZzg_^ozMt%!UM)$-u1KaB?0)%i)@SvLC-b2k0juOafc!vo)In z0c+Ix7-EdhUfsIYAZm#-C2pmxQ<}iHZneHQ71RM;Oe!~Wm6>0_vMg-Wdn80= zuR$ydUM$5LdZSb7H}yM^1{%ybEmg(TdeZF5O1s%o<8=a%;hEvQMHMst&+ zh%_EQP{GJAm1}n7tyu3gjlhVab1JMRz<<>_>$i<3etxgX3!4=$Bs>uk%TJJs8&8BH zv*d`ER_kACxJnaUaMl>w$Tg%R^iyHk4?w8=;2uGLSZOPwimtbsjhFuPRhuVywpzo0 zUy{SS3&p^QPAX}6bCIWxexl$vxj0((jlH%;VO-qKcVX+6aRw+SlFcsJ_q+-1Pow?s;M4=`uHPy-Ad)pTT$` zchbh?@p-=HN5}uWR0aYFxFP;T)2Qnr2g2yXrYgDY8pPy&kkNUjKI}x;Ck4+hW7|vcSLw2 z!KVi|wwJX=@s%1>#d1a6s^JKzK9R*U1TS2qFsJxOdDm1XuI_wDN6xT2egsPG!YIXGR z+%sM@*7u1%f$&&dT)sdj=>y-VKG;$fxjK#wLO5IMXHWqtlX5Wl`Dl&hAGeoWPk4)X zdSECS#KSuU9U>{iY9~W#)gNE}$VYJ5I0hdeb`j7&@&W#W4D_G(2>!Fg{;^~5->Lq6 z7vMjrlmVCjX;0wax%~aJmVaKI{e#(mlo5cu|M?@Af2aKCl+T~l+kX^ntbbX{{ddBD z&Mf?;xBo>63{ZQ(_Q=2TL;p_o&t~UO*5Myzj{Ki<5dTj1&v^US7d&JBR}=N`lz*P^ zcS!xg<39=&>;DU*|A5ZFGyVI1(0?!i0{Vl-f0Tg#hUx!<&A%zm--Y+jO7#bw|0rDm aX8$c#<)y&D|1^UF{CNZ3j*$J&-Twj6ROz|^ literal 0 HcmV?d00001 diff --git a/contrib/csv/vaillant/vwx.csv b/contrib/csv/vaillant/vwx.csv new file mode 100644 index 00000000..d95e6681 --- /dev/null +++ b/contrib/csv/vaillant/vwx.csv @@ -0,0 +1,107 @@ +# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment +get;vwx;BivalentTemp;Bivalenztemperatur;MS;08;B509;3;0D6500;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Bleeding;Entlüften;MS;08;B509;3;0D1300;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePress;Druck Solekreis;MS;08;B509;3;0D1600;2;press;sd;1,2;flt;0.001;bar;-;Druck;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;BrinePressSwitch;Soledruckschalter;MS;08;B509;3;0D2600;1;-;sd;1,2;sin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePumpCoolingRunTime;Kühlung Laufzeit Solepumpe;MS;08;B509;3;0D7D01;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePumpPower;Solepumpe Leistung;MS;08;B509;3;0DAC01;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePumpPowerHeating;Solepumpe Leistung beim Heizen;MS;08;B509;3;0DAE01;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePumpPreRunTime;Vorlaufzeit Quellenpumpe;MS;08;B509;3;0D7600;1;-;sd;1,4;ulg;-;min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePumpState;Solepumpe Status;MS;08;B509;3;0D1900;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrinePumpState;Solepumpe Status;MS;08;B509;3;0DB801;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;BrineTempInput;T3 Sole Temperatur Vorlauf – von Quelle;MS;08;B509;3;0D0F00;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;BrineTempOutput;T8 Sole Temperatur Rücklauf – zur Quelle;MS;08;B509;3;0D0800;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;CirculationPumpInput;Zirkulationspumpe Eingang;MS;08;B509;3;0D0B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CirculationPumpPower;Zirkulationspumpe Leistung;MS;23;B509;3;0DE601;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CirculationPumpState;Zirkulationspumpe Status;MS;08;B509;3;0D0C00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Code1;Code 1;MS;08;B509;3;0D9700;1;-;sd;1,2;uin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Code2;Code 2;MS;08;B509;3;0D9800;1;-;sd;1,2;uin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CodeValid;Code 1 und 2 gültig;MS;08;B509;3;0D2400;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CommutationState;Kompressor Kommunikationsstatus;MS;08;B509;3;0DAA00;1;-;sd;1,2,3,4;ulg;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CompressorNumberStarts;Kompressor Starts pro Stunde;MS;08;B509;3;0D7400;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CompressorState;Kompressor Status;MS;08;B509;3;0D1D00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;CompressorTempInput;T1 Kompressor Temperatur Eintritt;MS;08;B509;3;0D0200;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;CompressorTempOutput;T2 Kompressor Temperatur Austritt;MS;08;B509;3;0D0400;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;Date;Datum;MS;08;B509;3;0D2900;1;-;sd;1,2,3;hda;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;DeicingState;Enteisung Status;MS;08;B509;3;0DCE01;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;DeicingWaitTime;Enteisung Wartezeit zur nächsten Enteisung;MS;08;B509;3;0D7000;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;EvaporatorTemp;Verdampfer Temperatur;MS;08;B509;3;0D0500;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;ExpansionValveInputTemp;TEV Temperatur Eintritt;MS;08;B509;3;0D0D00;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;FlowTemp;VF2 Vorlauftemperatur IST;MS;08;B509;3;0D0300;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;FlowTempIntern;T6 interne Vorlauftempertur IST;MS;08;B509;3;0D0900;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;FrezzeProtectionTempMin;Einfrierschutz T81;MS;08;B509;3;0D7A01;1;-;sd;1;sch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;HeatPumpState;Heizkreispumpe Status;MS;08;B509;3;0D1700;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;HeatSystemPress;Heizanlagendruck;MS;08;B509;3;0D1200;2;press;sd;1,2;flt;0.001;bar;-;Druck;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;Hysteresis;Kompressor Hysterese;MS;08;B509;3;0D7D00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;InitialCurrentLimitation;Anlaufstrombegrenzung;MS;08;B509;3;0D3F00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Integral;Energieintegral;MS;08;B509;3;0D8000;1;-;sd;1,2;sin;-;°min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;IntegralStartValue;Energieintegral Startwert;MS;08;B509;3;0D7C00;1;-;sd;1,2;sin;-;°min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;MixerPosition;Mischer Position -100 – 100;MS;08;B509;3;0D0E00;1;-;sd;1;sch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;NoiseReductionFactor;Lautstärken Reduktion Faktor;MS;08;B509;3;0D2401;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;NoiseReductionState;Lautstärken Reduktion Status;MS;08;B509;3;0DA901;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Overheating;Überhitzung;MS;08;B509;3;0D8D00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;PhaseOrder;Drehfeld Status;MS;08;B509;3;0D5701;1;-;sd;1,2;sin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;PhaseState;Phasen Status;MS;08;B509;3;0D8800;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;PowerCutOff;EVU Sperrzeit – Stromunterbrechung;MS;08;B509;3;0D1100;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;PumpState;Pumpen Status;MS;08;B509;3;0D1800;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;RetrurnTempMax;Heizkreis Rücklauftemperatur MAX;MS;08;B509;3;0D7300;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;ReturnTempIntern;T5 interne Rücklauftempertur IST;MS;08;B509;3;0D0A00;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;RunTime;Kompressor Laufzeit Summe;MS;08;B509;3;0D9A00;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;RunTimeHeating;Kompressor Laufzeit Heizung;MS;08;B509;3;0D9B00;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;RunTimeHotWater;Kompressor Laufzeit Warmwasser;MS;08;B509;3;0D9C00;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;ServiceMode;Servicezeit;MS;08;B509;3;0D6600;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;SoftwareState;Software Status;MS;08;B509;3;0DCF00;1;-;sd;1,2,3,4;ulg;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;SwitchValve;Umschaltventil Heizen = 0 / Warmwasser = 1;MS;08;B509;3;0D1000;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;TempOutside;Aussentemperatur;MS;08;B509;3;0D0600;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;TempSpreadMax;Zulässige Temperaturspreizung T6 zu T7;MS;08;B509;3;0D6E00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Time;Uhrzeit;MS;08;B509;3;0D2800;1;-;sd;3,2,1;hti;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Undercooling;Unterkühlung;MS;08;B509;3;0D8E00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;VaporPressHigh;Hochdruck Kältekreis;MS;08;B509;3;0D1400;2;press;sd;1,2;flt;0.001;bar;-;Druck;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;VaporPressLow;Niederdruck Kältekreis;MS;08;B509;3;0D1500;2;press;sd;1,2;flt;0.001;bar;-;Druck;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwx;VaporPressostate;Kältekreis Über/Unterdruck Sicherheitsabschaltung;MS;08;B509;3;0D2500;1;-;sd;1,2;sin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;Weekday;Wochentag;MS;08;B509;3;0D2A00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwx;YieldEnvironmentEnergy;Energieertrag Umgebung;MS;08;B509;3;0DBC00;1;-;sd;1,2,3,4;ulg;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;BrineTempInput;Kalibrierung Quelle Eintritt;MS;08;B509;3;0DCD00;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;BrineTempOutput;Kalibrierung Quelle Austritt;MS;08;B509;3;0DC900;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;CompressorTempInput;Kalibrierung Kompressor Eintritt;MS;08;B509;3;0DC600;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;CompressorTempOutput;Kalibrierung Kompressor Austritt;MS;08;B509;3;0DC700;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;FlowTemp;Kalibrierung Vorlauftemperatur VF1;MS;08;B509;3;0DCA00;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;FlowTempVF2;Kalibrierung VF2 Temperatur;MS;08;B509;3;0DC500;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;HotWaterTemp;Kalibrierung Warmwassertemperatur;MS;08;B509;3;0DC400;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;OutsideTemp;Kalibrierung Aussentemperatur;MS;08;B509;3;0DC300;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;ReturnTemp;Kalibrierung Rücklauftemperatur RF1;MS;08;B509;3;0DCB00;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;TankTempBottom;Kalibrierung Speicher Bodentemperatur;MS;08;B509;3;0D3401;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxcal;TankTempTop;Kalibrierung Speicher Kopftemperatur;MS;08;B509;3;0D3301;1;-;sd;1,2;d2c;1.0;K;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;CommutationState;Zusatzheizung Kommunikationsstatus;MS;08;B509;3;0DB100;1;-;sd;1,2,3,4;ulg;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;ElectricHeaterModeHeat;Zusatzheizung für Warmwasser;MS;08;B509;3;0D6300;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;ElectricHeaterModeHotWater;Zusatzheizung für Heizung;MS;08;B509;3;0D6400;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;ElectricHeaterState;Zusatzheizung Status;MS;08;B509;3;0D5F00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;ElectricHeaterType;Zusatzheizung Typ;MS;08;B509;3;0D9200;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;Hysteresis;Zusatzheizung Hysterese;MS;08;B509;3;0D7E00;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;IntegralStartValue;Zusatzheizung Energieintegral Startwert;MS;08;B509;3;0D7F00;1;-;sd;1,2;sin;-;°min;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;RunTime;Zusatzheizung Laufzeit Summe;MS;08;B509;3;0DA100;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;RunTimeHeating;Zusatzheizung Laufzeit Heizung;MS;08;B509;3;0DA200;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxeh;RunTimeHotWater;Zusatzheizung Laufzeit Warmwasser;MS;08;B509;3;0DA300;1;-;sd;1,2,3,4;ulg;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxhw;FlowTemp;VF1 Bufferspeicher Kopftemperatur;MS;08;B509;3;0D0100;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwxhw;HotWaterTempMax;Warmwasser Termperatur MAX;MS;25;B509;3;0D8200;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxhw;HotWaterTempMin;Warmwasser Termperatur MIN;MS;25;B509;3;0D8300;1;-;sd;1,2;d2c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxhw;LegionellaProtectionActive;Legionellenfunktion aktivert;MS;25;B509;3;0D4000;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxhw;LegionellaProtectionDay;Legionellenfunktion Wochentag;MS;25;B509;3;0D7C01;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxhw;LegionellaProtectionTime;Legionellenfunktion Zeitpunkt;MS;25;B509;3;0D6700;2;hh;sd;1;uch;-;h;-;Stunde;mm;sd;2;uch;-;min;-;Minute;;;;;;;;;;;;;;;; +get;vwxhw;OperatingMode;Betriebsart;MS;25;B509;3;0D2B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxhw;ReturnTemp;RF1 Bufferspeicher Bodentemperatur;MS;08;B509;3;0D0700;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwxhw;TankTemp;Speichertemperatur IST;MS;08;B509;3;0D0000;2;temp;sd;1,2;d2c;1.0;°C;-;Temperatur;sensor;sd;3;uch;-;-;-;Fühler;;;;;;;;;;;;;;;; +get;vwxhw;TankTypePipe;Speichertyp ist Rohr;MS;25;B509;3;0DCD01;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;CoolingOperatingMode;Kühlung Betriebsart;MS;50;B509;3;0D8C01;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;DesiredTemp;Solltemperatur;MS;50;B509;3;0D3200;1;-;sd;1;d1c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;DesiredTempLow;Absenktemperatur;MS;50;B509;3;0D3300;1;-;sd;1;d1c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;FloorProtectionTempLimit;Fußbodenschutz Temp > VF2;MS;50;B509;3;0D7B01;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;FloorScreedDryingDay;Estrichtrocknung Tag;MS;50;B509;3;0D3B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;FlowTempDesired;Vorlauftemperatur Soll;MS;50;B509;3;0D4600;1;-;sd;1;d1c;1.0;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;HeatingCircuitType;Heizkreistyp;MS;50;B509;3;0D3C00;1;-;sd;1,2;sin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;HeatingCurve;Heizkurve;MS;50;B509;3;0D3500;1;-;sd;1,2;uin;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;OperatingMode;Betriebsart;MS;50;B509;3;0D2B00;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;OutsideTempLimitShutdown;Abschaltgrenze Aussentempertur;MS;50;B509;3;0D3600;1;-;sd;1;uch;-;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;PreHeatingTimeMax;Voraufheizung MAX;MS;50;B509;3;0D3800;1;-;sd;1;uch;-;h;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;PumpPower;Pumpen Leistung;MS;50;B509;3;0DBA01;1;-;sd;1;uch;-;%;-;-;;;;;;;;;;;;;;;;;;;;;;;; +get;vwxmk;PumpState;Pumpen Status;MS;50;B509;3;0DB901;1;-;sd;1;uch;-;-;-;-;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/contrib/csv/vaillant/vwx.ods b/contrib/csv/vaillant/vwx.ods new file mode 100644 index 0000000000000000000000000000000000000000..65cbb4f01498de125aca4102ab9e2774a431e483 GIT binary patch literal 20557 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 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "baseloop.h" +#include "logger.h" +#include "appl.h" +#include "network.h" +#include +#include +#include + +extern LogInstance& L; +extern Appl& A; + +void BaseLoop::start() +{ + for (;;) { + // recv new message from client + Message* message = m_queue.remove(); + std::string data = message->getData(); + + data.erase(std::remove(data.begin(), data.end(), '\r'), data.end()); + data.erase(std::remove(data.begin(), data.end(), '\n'), data.end()); + + L.log(bas, event, ">>> %s", data.c_str()); + + // decode message + std::string result(decodeMessage(data)); + + L.log(bas, event, "<<< %s", result.c_str()); + + // send result to client + result += '\n'; + Connection* connection = static_cast(message->getSource()); + connection->addResult(Message(result.c_str())); + + delete message; + } +} + +std::string BaseLoop::decodeMessage(const std::string& data) +{ + std::ostringstream result; + std::string value; + int index; + BusCommand* busCommand; + + // prepare data + std::string token; + std::istringstream stream(data); + std::vector cmd; + + // split stream + while (std::getline(stream, token, ' ') != 0) + cmd.push_back(token); + + if (cmd.size() == 0) + return "command missing"; + + switch (getCase(cmd[0])) { + case notfound: + result << "command not found"; + break; + + case get: + case set: + if (cmd.size() < 3) { + result << "format: type class cmd [sub]"; + break; + } + + index = m_commands->findCommand(data); + + if (index >= 0) { + + std::string type = m_commands->getType(index); + std::string cmd(A.getParam("p_address")); + cmd += m_commands->getCommand(index); + std::transform(cmd.begin(), cmd.end(), cmd.begin(), tolower); + + L.log(bas, trace, " type: %s msg: %s", type.c_str(), cmd.c_str()); + // send BusCommand + m_ebusloop->addBusCommand(new BusCommand(type, cmd)); + busCommand = m_ebusloop->getBusCommand(); + + // decode BusCommand + result << busCommand->getResult().c_str(); + delete busCommand; + + } else { + result << "ebus command not found"; + } + + break; + + case cyc: + if (cmd.size() < 3) { + result << "format: type class cmd [sub]"; + break; + } + + index = m_commands->findCommand(data); + + if (index >= 0) { + value = m_cycdata->getData(index); + if (value != "") { + // decode CYC Data + result << value.c_str(); + } else { + result << "no data stored"; + } + } else { + result << "ebus command not found"; + } + + break; + + case dump: + if (cmd[1] == "on") m_ebusloop->dump(true); + if (cmd[1] == "off") m_ebusloop->dump(false); + result << "done"; + break; + + case log: + if (cmd[1] == "error") L.getSink(0)->setLevel(error); + if (cmd[1] == "event") L.getSink(0)->setLevel(event); + if (cmd[1] == "trace") L.getSink(0)->setLevel(trace); + if (cmd[1] == "debug") L.getSink(0)->setLevel(debug); + result << "done"; + break; + + default: + break; + } + + return result.str(); +} + diff --git a/src/baseloop.h b/src/baseloop.h new file mode 100644 index 00000000..37549f63 --- /dev/null +++ b/src/baseloop.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef BASELOOP_H_ +#define BASELOOP_H_ + +#include "libebus.h" +#include "ebusloop.h" +#include "cycdata.h" +#include "wqueue.h" +#include + +using namespace libebus; + +class Connection; + +class Message +{ + +public: + Message(const std::string data, void* source = NULL) : m_data(data), m_source(source) {} + Message(const Message& src) : m_data(src.m_data), m_source(src.m_source) {} + + std::string getData() const { return m_data.c_str(); } + void* getSource() const { return m_source; } + +private: + std::string m_data; + void* m_source; + +}; + +class BaseLoop +{ + +public: + BaseLoop(EBusLoop* ebusloop, CYCData* cycdata, Commands* commands) + : m_ebusloop(ebusloop), m_cycdata(cycdata), m_commands(commands) {} + + void start(); + + WQueue* getQueue() { return &m_queue; } + void addMessage(Message* message) { m_queue.add(message); } + +private: + EBusLoop* m_ebusloop; + CYCData* m_cycdata; + Commands* m_commands; + WQueue m_queue; + + enum ClientCommand { + get, // get ebus data + set, // set ebus value + cyc, // fetch cycle data + dump, // change dump state + log, // change log level + + notfound + }; + + ClientCommand getCase(const std::string& item) + { + if (item == "get") return get; + if (item == "set") return set; + if (item == "cyc") return cyc; + if (item == "dump") return dump; + if (item == "log") return log; + + return notfound; + } + + std::string decodeMessage(const std::string& data); + +}; + +#endif // BASELOOP_H_ diff --git a/src/cycdata.cpp b/src/cycdata.cpp new file mode 100644 index 00000000..25a57d7d --- /dev/null +++ b/src/cycdata.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "cycdata.h" +#include "logger.h" + +extern LogInstance& L; + +CYCData::~CYCData() +{ + for (mapCI_t iter = m_cycDB.begin(); iter != m_cycDB.end(); ++iter) + delete iter->second; +} + +void* CYCData::run() +{ + bool skipfirst = false; + + for (;;) { + std::string data = m_ebusloop->getData(); + + if (skipfirst == true) { + L.log(cyc, trace, "%s", data.c_str()); + + int index = m_commands->findData(data); + + if (index >= 0) { + std::string tmp; + tmp += (*m_commands)[index][0]; + tmp += " "; + tmp += (*m_commands)[index][1]; + tmp += " "; + tmp += (*m_commands)[index][2]; + L.log(cyc, trace, " [%d] %s", index, tmp.c_str()); + storeData(index, data); + } + } + + skipfirst = true; + + if (m_stop == true) + return NULL; + } + + return NULL; +} + +void CYCData::storeData(int index, std::string data) +{ + mapCI_t iter = m_cycDB.find(index); + + if (iter != m_cycDB.end()) { + iter->second->setData(data); + L.log(cyc, debug, " [%d] %s -> replaced", index, data.c_str()); + } else { + Command* cmd = new Command(index, (*m_commands)[index], data); + m_cycDB.insert(pair_t(index, cmd)); + L.log(cyc, debug, " [%d] %s -> inserted", index, data.c_str()); + } + + L.log(cyc, debug, " cycDB entries: %d", m_cycDB.size()); +} + +std::string CYCData::getData(int index) +{ + mapCI_t iter = m_cycDB.find(index); + if (iter != m_cycDB.end()) + return iter->second->getData(); + else + return ""; +} + diff --git a/src/cycdata.h b/src/cycdata.h new file mode 100644 index 00000000..2596b7e2 --- /dev/null +++ b/src/cycdata.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef CYCDATA_H_ +#define CYCDATA_H_ + +#include "libebus.h" +#include "ebusloop.h" +#include "thread.h" +#include + +using namespace libebus; + +typedef std::map map_t; +typedef map_t::const_iterator mapCI_t; +typedef std::pair pair_t; + +class CYCData : public Thread +{ + +public: + CYCData(EBusLoop* ebusloop, Commands* commands) + : m_ebusloop(ebusloop), m_commands(commands), m_stop(false) {} + ~CYCData(); + + void* run(); + void stop() { m_stop = true; } + + std::string getData(int index); + +private: + EBusLoop* m_ebusloop; + Commands* m_commands; + map_t m_cycDB; + bool m_stop; + + void storeData(int index, std::string data); +}; + +#endif // CYCDATA_H_ diff --git a/src/ebusloop.cpp b/src/ebusloop.cpp new file mode 100644 index 00000000..e54b2282 --- /dev/null +++ b/src/ebusloop.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "ebusloop.h" +#include "logger.h" +#include "appl.h" +#include + +extern LogInstance& L; +extern Appl& A; + +EBusLoop::EBusLoop() : m_stop(false) +{ + m_deviceName = A.getParam("p_device"); + + m_bus = new Bus(m_deviceName, + A.getParam("p_nodevicecheck"), + A.getParam("p_dumpfile"), + A.getParam("p_dumpsize"), + A.getParam("p_dump")); + + m_bus->connect(); + + if (m_bus->isConnected() == false) + L.log(bus, error, "can't open %s", m_deviceName.c_str()); +} + +EBusLoop::~EBusLoop() +{ + m_bus->disconnect(); + + if (m_bus->isConnected() == true) + L.log(bus, error, "error during disconnect."); + + delete m_bus; +} + +void* EBusLoop::run() +{ + int busResult; + bool busCommandActive = false; + + for (;;) { + if (m_bus->isConnected() == true) { + + // work on bus + busResult = m_bus->proceed(); + + // new cyc message arrived + if (busResult == 2) { + std::string data = m_bus->getCycData(); + //~ L.log(bus, trace, "%s", data.c_str()); + m_cycBuffer.add(data); + } + + // add new bus command to send + if (busResult == 4 && busCommandActive == false && m_sendBuffer.size() != 0) { + BusCommand* busCommand = m_sendBuffer.remove(); + m_bus->addCommand(busCommand); + busCommandActive = true; + } + + // send bus command + if (busResult == 1 && busCommandActive == true) { + L.log(bus, trace, " getBus success"); + m_bus->sendCommand(); + BusCommand* busCommand = m_bus->recvCommand(); + m_recvBuffer.add(busCommand); + busCommandActive = false; + } + + if (busResult == 0) + L.log(bus, trace, " getBus failure"); + + if (busResult == -1) + L.log(bus, event, " getBus error"); + + } else { + sleep(10); + m_bus->connect(); + + if (m_bus->isConnected() == false) + L.log(bus, error, "can't open %s", m_deviceName.c_str()); + } + + if (m_stop == true) { + m_bus->disconnect(); + return NULL; + } + } + + return NULL; +} + diff --git a/src/ebusloop.h b/src/ebusloop.h new file mode 100644 index 00000000..53b9fd5c --- /dev/null +++ b/src/ebusloop.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef EBUSLOOP_H_ +#define EBUSLOOP_H_ + +#include "libebus.h" +#include "wqueue.h" +#include "thread.h" + +using namespace libebus; + + +class EBusLoop : public Thread +{ + +public: + EBusLoop(); + ~EBusLoop(); + + void* run(); + void stop() { m_stop = true; } + + std::string getData() { return m_cycBuffer.remove(); } + + void addBusCommand(BusCommand* busCommand) { m_sendBuffer.add(busCommand); } + BusCommand* getBusCommand() { return m_recvBuffer.remove(); } + + void dump(const bool dumpState) { m_bus->setDumpState(dumpState); } + +private: + std::string m_deviceName; + Bus* m_bus; + WQueue m_cycBuffer; + bool m_stop; + WQueue m_sendBuffer; + WQueue m_recvBuffer; + +}; + +#endif // EBUSLOOP_H_ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 00000000..eb6e6874 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ +#include "libebus.h" +#include "logger.h" +#include "daemon.h" +#include "appl.h" +#include "network.h" +#include "ebusloop.h" +#include "cycdata.h" +#include "baseloop.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace libebus; + +Appl& A = Appl::Instance(); +Daemon& D = Daemon::Instance(); +LogInstance& L = LogInstance::Instance(); + +Network* network; +Commands* commands; +EBusLoop* ebusloop; +CYCData* cycdata; + +void define_args() +{ + A.addItem("p_address", Appl::Param("FF"), "a", "address", + "\tebus device address (FF)", + Appl::type_string, Appl::opt_mandatory); + + A.addItem("p_device", Appl::Param("/dev/ttyUSB0"), "d", "device", + "\tebus device (serial or network) (/dev/ttyUSB0)", + Appl::type_string, Appl::opt_mandatory); + + A.addItem("p_nodevicecheck", Appl::Param(false), "n", "nodevicecheck", + "disable valid ebus device test\n", Appl::type_bool, Appl::opt_none); + + A.addItem("p_ebusconfdir", Appl::Param("contrib/csv/vaillant"), "e", "ebusconfdir", + "directory for ebus configuration (contrib/csv/vaillant)\n", + Appl::type_string, Appl::opt_mandatory); + + A.addItem("p_foreground", Appl::Param(false), "f", "foreground", + "run in foreground\n", Appl::type_bool, Appl::opt_none); + + A.addItem("p_port", Appl::Param(8888), "p", "port", + "\tlisten port (8888)", Appl::type_int, Appl::opt_mandatory); + + A.addItem("p_localhost", Appl::Param(false), "", "localhost", + "listen localhost only\n", Appl::type_bool, Appl::opt_none); + + A.addItem("p_area", Appl::Param(all), "", "logarea", + "\tlogging area (bas=1, net=2, bus=4, cyc=8, all=15)", + Appl::type_int, Appl::opt_mandatory); + + A.addItem("p_level", Appl::Param(trace), "", "loglevel", + "\tlogging level (error=1, event=2, trace=3, debug=4)\n", + Appl::type_int, Appl::opt_mandatory); + + A.addItem("p_dump", Appl::Param(false), "D", "dump", + "\tenable dump", Appl::type_bool, Appl::opt_none); + + A.addItem("p_dumpfile", Appl::Param("/tmp/dump_ebusd.bin"), "", "dumpfile", + "\tdump file name (/tmp/dump_ebusd.bin)", Appl::type_string, Appl::opt_mandatory); + + A.addItem("p_dumpsize", Appl::Param(100), "", "dumpsize", + "\tmax size for dump file in kB (100)\n", Appl::type_long, Appl::opt_mandatory); + + A.addItem("p_help", Appl::Param(false), "h", "help", + "\tprint this message", Appl::type_bool, Appl::opt_none); +} + +void shutdown() +{ + // free Network + if (network != NULL) + delete network; + + // free CYCData + if (cycdata != NULL) { + cycdata->stop(); + delete cycdata; + } + + // free EBusLoop + if (ebusloop != NULL) { + ebusloop->stop(); + ebusloop->join(); + delete ebusloop; + } + + // free Commands DB + if (commands != NULL) + delete commands; + + // reset all signal handlers to default + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + + // delete Daemon pid file + if (D.status() == true) + D.stop(); + + // stop Logger + L.log(bas, event, "ebusd stopped"); + L.stop(); + L.join(); + + exit(EXIT_SUCCESS); +} + +void signal_handler(int sig) +{ + switch (sig) { + case SIGHUP: + L.log(bas, event, "SIGHUP received"); + break; + case SIGINT: + L.log(bas, event, "SIGINT received"); + shutdown(); + break; + case SIGTERM: + L.log(bas, event, "SIGTERM received"); + shutdown(); + break; + default: + L.log(bas, event, "undefined signal %s", strsignal(sig)); + break; + } +} + +int main(int argc, char* argv[]) +{ + // define Arguments and Application variables + define_args(); + + // parse Arguments + if (A.parse(argc, argv) == false) { + A.printArgs(); + exit(EXIT_FAILURE); + } + + // print Help + if (A.getParam("p_help") == true) { + A.printArgs(); + exit(EXIT_SUCCESS); + } + + // make me Daemon + if (A.getParam("p_foreground") == true) { + L += new LogConsole(A.getParam("p_area"), + static_cast(A.getParam("p_level")), "logConsole"); + } else { + D.run("/var/run/ebusd.pid"); + L += new LogFile(A.getParam("p_area"), + static_cast(A.getParam("p_level")), "logFile", "/var/log/ebusd.log"); + } + + // trap Signals that we expect to receive + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + // start Logger + L.start("logInstance"); + L.log(bas, event, "ebusd started"); + + // print Daemon status + if (D.status() == true) + L.log(bas, event, "change to daemon"); + + // create Commands DB + commands = ConfigCommands(A.getParam("p_ebusconfdir"), CSV).getCommands(); + L.log(bas, event, "commands DB with %d entries created", commands->size()); + + // create EBusLoop + ebusloop = new EBusLoop(); + ebusloop->start("ebusloop"); + + // create CYCData + cycdata = new CYCData(ebusloop, commands); + cycdata->start("cycdata"); + + // create Network + network = new Network(A.getParam("p_localhost")); + + // create BaseLoop + BaseLoop baseloop(ebusloop, cycdata, commands); + + // start Network + network->addQueue(baseloop.getQueue()); + network->start("netListener"); + + // start Baseloop + baseloop.start(); + + shutdown(); +} + diff --git a/src/network.cpp b/src/network.cpp new file mode 100644 index 00000000..c4b74487 --- /dev/null +++ b/src/network.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "network.h" +#include "logger.h" +#include "appl.h" +#include +#include +#include + +extern LogInstance& L; +extern Appl& A; + +int Connection::m_count = -1; + +void Connection::addResult(Message message) +{ + Message* tmp = new Message(Message(message)); + m_result.add(tmp); +} + +void* Connection::run() +{ + m_running = true; + + int maxfd; + fd_set checkfds; + struct timeval timeout; + + FD_ZERO(&checkfds); + FD_SET(m_notify.notifyFD(), &checkfds); + FD_SET(m_socket->getFD(), &checkfds); + + (m_notify.notifyFD() > m_socket->getFD()) ? + (maxfd = m_notify.notifyFD()) : (maxfd = m_socket->getFD()); + + for (;;) { + fd_set readfds; + int ret; + + // set select timeout 10 secs + timeout.tv_sec = 10; + timeout.tv_usec = 0; + + // set readfds to inital checkfds + readfds = checkfds; + + ret = select(maxfd + 1, &readfds, NULL, NULL, &timeout); + if (ret == 0) { + continue; + } + + // new data from notify + if (FD_ISSET(m_notify.notifyFD(), &readfds)) + break; + + // new data from socket + if (FD_ISSET(m_socket->getFD(), &readfds)) { + char data[256]; + size_t datalen; + + if (m_socket->isValid() == true) + datalen = m_socket->recv(data, sizeof(data)-1); + else + break; + + // removed closed socket + if (datalen <= 0 || strncasecmp(data, "quit", 4) == 0) + break; + + // send data + data[datalen] = '\0'; + m_data->add(new Message(data, this)); + + // wait for result + L.log(net, debug, "[%08x] wait for result", getID()); + Message* message = m_result.remove(); + + L.log(net, debug, "[%08x] result added", getID()); + std::string result(message->getData()); + + if (m_socket->isValid() == true) + m_socket->send(result.c_str(), result.size()); + else + break; + + delete message; + + } + + } + + delete m_socket; + m_running = false; + L.log(net, event, "[%08x] connection closed - active connections: %d", getID(), m_count); + + return NULL; +} + + + +Network::Network(const bool localhost) : m_listening(false), m_running(false) +{ + // Start Listener + if (localhost == true) + m_Listener = new TCPListener(A.getParam("p_port"), "127.0.0.1"); + else + m_Listener = new TCPListener(A.getParam("p_port"), "0.0.0.0"); + + if (m_Listener && m_Listener->start() == 0) + m_listening = true; + +} + +Network::~Network() +{ + while (m_connections.empty() == false) { + Connection* connection = m_connections.back(); + m_connections.pop_back(); + connection->stop(); + connection->join(); + delete connection; + } + + if (m_running == true) + stop(); + + delete m_Listener; +} + +void* Network::run() +{ + if (m_listening == false) + return NULL; + + m_running = true; + + int maxfd; + fd_set checkfds; + struct timeval timeout; + + FD_ZERO(&checkfds); + FD_SET(m_notify.notifyFD(), &checkfds); + FD_SET(m_Listener->getFD(), &checkfds); + + (m_notify.notifyFD() > m_Listener->getFD()) ? + (maxfd = m_notify.notifyFD()) : (maxfd = m_Listener->getFD()); + + for (;;) { + fd_set readfds; + int ret; + + // set select timeout 1 secs + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + // set readfds to inital checkfds + readfds = checkfds; + + ret = select(maxfd + 1, &readfds, NULL, NULL, &timeout); + if (ret == 0) { + cleanConnections(); + continue; + } + + // new data from notify + if (FD_ISSET(m_notify.notifyFD(), &readfds)) { + m_running = false; + break; + } + + // new data from socket + if (FD_ISSET(m_Listener->getFD(), &readfds)) { + TCPSocket* socket = m_Listener->newSocket(); + if (socket == NULL) + continue; + + Connection* connection = new Connection(socket, m_queue); + if (connection == NULL) + continue; + + connection->start("netConnection"); + m_connections.push_back(connection); + L.log(net, event, "[%08x] connection opened %s", connection->getID(), socket->getIP().c_str()); + } + + } + + return NULL; +} + +void Network::cleanConnections() +{ + std::list::iterator c_it; + for (c_it = m_connections.begin(); c_it != m_connections.end(); c_it++) { + if ((*c_it)->isRunning() == false) { + Connection* connection = *c_it; + c_it = m_connections.erase(c_it); + delete connection; + L.log(net, debug, "dead connection removed - %d", m_connections.size()); + } + } +} + diff --git a/src/network.h b/src/network.h new file mode 100644 index 00000000..8642857f --- /dev/null +++ b/src/network.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef NETWORK_H_ +#define NETWORK_H_ + +#include "tcpsocket.h" +#include "wqueue.h" +#include "thread.h" +#include "notify.h" +#include "baseloop.h" +#include +#include + +class Connection : public Thread +{ + +public: + Connection(TCPSocket* socket, WQueue* data) + : m_socket(socket), m_data(data), m_running(false) { m_count++; } + + ~Connection() { m_count--; } + + void addResult(Message message); + + void* run(); + void stop() const { m_notify.notify(); } + bool isRunning() const { return m_running; } + + pthread_t getID() { return this->self(); } + int numConnections() const { return m_count; } + +private: + TCPSocket* m_socket; + WQueue* m_data; + WQueue m_result; + Notify m_notify; + bool m_running; + + static int m_count; + +}; + +class Network : public Thread +{ + +public: + Network(const bool localhost); + ~Network(); + + void addQueue(WQueue* queue) { m_queue = queue; } + + void* run(); + void stop() const { m_notify.notify(); usleep(100000); } + +private: + std::list m_connections; + WQueue* m_queue; + TCPListener* m_Listener; + Notify m_notify; + bool m_listening; + bool m_running; + + void cleanConnections(); + +}; + +#endif // NETWORK_H_ diff --git a/test/feed.cpp b/test/feed.cpp new file mode 100644 index 00000000..b01f8344 --- /dev/null +++ b/test/feed.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "libebus.h" +#include "appl.h" +#include +#include +#include +#include +#include +#include + +using namespace libebus; + +Appl& A = Appl::Instance(); + +void define_args() +{ + A.addItem("p_device", Appl::Param("/dev/ttyUSB60"), "d", "device", + "dummy serial device (/dev/ttyUSB60)\n\t\t(socat -d -d pty,raw,echo=0 pty,raw,echo=0)", + Appl::type_string, Appl::opt_mandatory); + + A.addItem("p_file", Appl::Param("test/scan_ebusd.bin"), "f", "file", + "dump file with raw data (test/scan_ebusd.bin)", + Appl::type_string, Appl::opt_mandatory); + + A.addItem("p_time", Appl::Param(10000), "t", "time", + "wait time [ms] (10000)", Appl::type_long, Appl::opt_mandatory); + + A.addItem("p_help", Appl::Param(false), "h", "help", + "print this message", Appl::type_bool, Appl::opt_none); +} + +int main(int argc, char* argv[]) +{ + // define Arguments and Application variables + define_args(); + + // parse Arguments + if (A.parse(argc, argv) == false) { + A.printArgs(); + exit(EXIT_FAILURE); + } + + // print Help + if (A.getParam("p_help") == true) { + A.printArgs(); + exit(EXIT_SUCCESS); + } + + + std::string dev(A.getParam("p_device")); + Port port(dev, true); + + port.open(); + if(port.isOpen() == true) + std::cout << "openPort successful." << std::endl; + + + std::fstream file(A.getParam("p_file"), std::ios::in | std::ios::binary); + + if(file.is_open() == true) { + + while (file.eof() == false) { + unsigned char byte = file.get(); + std::cout << std::hex << std::setw(2) << std::setfill('0') + << static_cast(byte) << std::endl; + + port.send(&byte, 1); + usleep(A.getParam("p_time")); + } + + file.close(); + } + + + port.close(); + if(port.isOpen() == false) + std::cout << "closePort successful." << std::endl; + + return 0; + +} diff --git a/test/scan_ebusd.bin b/test/scan_ebusd.bin new file mode 100644 index 0000000000000000000000000000000000000000..64299892bf4227f5e057b9c6df5631c4e2ec5d00 GIT binary patch literal 18 YcmZ3r>i;T%e_L5u)EN{QzOMoT09B0$umAu6 literal 0 HcmV?d00001 diff --git a/utils/appl.cpp b/utils/appl.cpp new file mode 100644 index 00000000..63c3ce5c --- /dev/null +++ b/utils/appl.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "appl.h" +#include +#include +#include + +Appl& Appl::Instance() +{ + static Appl instance; + return instance; +} + +Appl::~Appl() +{ + m_args.clear(); + m_params.clear(); +} + +void Appl::addItem(const char* name, Param param, const char* shortname, + const char* longname, const char* description, + Datatype datatype, Optiontype optiontype) +{ + if (strlen(name) != 0) + m_params[name] = param; + + if (strlen(longname) != 0) { + Arg arg; + arg.name = name; + arg.shortname = shortname; + arg.longname = longname; + arg.description = description; + arg.datatype = datatype; + arg.optiontype = optiontype; + m_args.push_back(arg); + } +} + +void Appl::printArgs() +{ + std::cerr << std::endl << "Usage:" << std::endl << " " + << m_argv[0].substr(2) << " [Options]" << std::endl + << std::endl << "Options:" << std::endl; + + for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) { + const char* c = (strlen(a_it->shortname) == 1) ? a_it->shortname : " "; + std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c + << " | --" << a_it->longname + << "\t" << a_it->description + << std::endl; + } + + std::cerr << std::endl; +} + +bool Appl::parse(int argc, char* argv[]) +{ + std::vector _argv(argv, argv + argc); + m_argc = argc; + m_argv = _argv; + + for (int i = 1; i < m_argc; i++) { + + // find option with long format '--' + if (m_argv[i].rfind("--") == 0 && m_argv[i].size() > 2) { + + // is next item an added argument? + if (i+1 < m_argc && m_argv[i+1].rfind("-") == std::string::npos) { + if (checkArg(m_argv[i].substr(2), m_argv[i+1]) == false) + return false; + } else { + if (checkArg(m_argv[i].substr(2), "") == false) + return false; + } + + // find option with short format '-' + } else if (m_argv[i].rfind("-") == 0 && m_argv[i].size() > 1) { + + // walk through all characters + for (size_t j = 1; j < m_argv[i].size(); j++) { + + // only last charater could have an argument + if (i+1 < m_argc && m_argv[i+1].rfind("-") == std::string::npos + && j+1 == m_argv[i].size()) { + if (checkArg(m_argv[i].substr(j,1), m_argv[i+1]) == false) + return false; + } else { + if (checkArg(m_argv[i].substr(j,1), "") == false) + return false; + } + } + } + + } + return true; +} + +bool Appl::checkArg(const std::string name, const std::string arg) +{ + for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) { + if (a_it->shortname == name || a_it->longname == name) { + + if (a_it->optiontype == opt_mandatory && arg.size() == 0) { + std::cerr << std::endl << "option requires an argument '" + << name << "'" << std::endl; + return false; + } + + if ((a_it->optiontype == opt_optional && arg.size() != 0) + || a_it->optiontype != opt_optional) + addParam(a_it->name, arg, a_it->datatype); + + return true; + } + } + + std::cerr << m_argv[0].substr(2) << ": Unknown Option -- " << name << std::endl; + return false; +} + +void Appl::addParam(const char* name, const std::string arg, Datatype datatype) +{ + switch (datatype) { + case type_bool: + m_params[name] = true; + break; + case type_int: + m_params[name] = atoi(arg.c_str()); + break; + case type_long: + m_params[name] = atol(arg.c_str()); + break; + case type_float: + m_params[name] = (float) atof(arg.c_str()); + break; + case type_string: + m_params[name] = arg.c_str(); + break; + default: + break; + } +} + + diff --git a/utils/appl.h b/utils/appl.h new file mode 100644 index 00000000..a7d8a92b --- /dev/null +++ b/utils/appl.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef APPL_H_ +#define APPL_H_ + +#include +#include +#include +#include + +class Appl +{ + +private: + struct Option; + +public: + enum Datatype { type_none, type_bool, type_int, type_long, type_float, type_string }; + enum Optiontype { opt_none, opt_optional, opt_mandatory }; + + union Param { + bool b; + int i; + long l; + float f; + const char* c; + + Param() { memset(this, 0, sizeof(Param)); } + Param(bool _b) : b(_b) {} + Param(int _i) : i(_i) {} + Param(long _l) : l(_l) {} + Param(float _f) : f(_f) {} + Param(const char* _c) : c(_c) {} + }; + + template + T getParam(const char* name) + { + p_it = m_params.find(name); + return (reinterpret_cast(p_it->second)); + } + + static Appl& Instance(); + + ~Appl(); + + void addItem(const char* name, Param param, const char* shortname, + const char* longname, const char* description, + Datatype datatype, Optiontype optiontype); + + void printArgs(); + + bool parse(int argc, char* argv[]); + +private: + Appl() {} + Appl(const Appl&); + Appl& operator= (const Appl&); + + struct Arg { + const char* name; + const char* shortname; + const char* longname; + const char* description; + Datatype datatype; + Optiontype optiontype; + }; + + int m_argc; + std::vector m_argv; + + std::vector m_args; + std::vector::const_iterator a_it; + + std::map m_params; + std::map::iterator p_it; + + bool checkArg(const std::string name, const std::string arg); + + void addParam(const char* name, Param param) { m_params[name] = param; } + + void addParam(const char* name, const std::string arg, Datatype datatype); +}; + +#endif // APPL_H_ diff --git a/utils/daemon.cpp b/utils/daemon.cpp new file mode 100644 index 00000000..5f276d29 --- /dev/null +++ b/utils/daemon.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "daemon.h" +#include +#include +#include +#include +#include +#include +#include + +Daemon& Daemon::Instance() +{ + static Daemon instance; + return instance; +} + +void Daemon::run(const char* file) +{ + m_status = false; + m_pidfile = file; + m_pidfd = 0; + + pid_t pid; + + // fork off the parent process + pid = fork(); + + if (pid < 0) { + std::cerr << "ebusd fork() failed." << std::endl; + exit(EXIT_FAILURE); + } + + // If we got a good PID, then we can exit the parent process + if (pid > 0) { + // printf("Child process created: %d\n", pid); + exit(EXIT_SUCCESS); + } + + // At this point we are executing as the child process + + // Set file permissions 750 + umask(027); + + // Create a new SID for the child process and + // detach the process from the parent (normally a shell) + if (setsid() < 0) { + std::cerr << "ebusd setsid() failed." << std::endl; + exit(EXIT_FAILURE); + } + + // Change the current working directory. This prevents the current + // directory from being locked; hence not being able to remove it. + if (chdir("/tmp") < 0) { //DAEMON_WORKDIR + std::cerr << "ebusd chdir() failed." << std::endl; + exit(EXIT_FAILURE); + } + + // Close stdin, stdout and stderr + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + // write pidfile and try to lock it + if (pidfile_open() == false) { + std::cerr << "can't open pidfile: %s" << m_pidfile << std::endl; + exit(EXIT_FAILURE); + } + + m_status = true; +} + +bool Daemon::pidfile_open() +{ + char pid[10]; + + m_pidfd = open(m_pidfile, O_RDWR|O_CREAT, 0600); + if (m_pidfd < 0) + return false; + + if (lockf(m_pidfd, F_TLOCK, 0) < 0) + return false; + + sprintf(pid, "%d\n", getpid()); + if (write(m_pidfd, pid, strlen(pid)) < 0) + return false; + + return true; +} + +bool Daemon::pidfile_close() +{ + if (close(m_pidfd) < 0) + return false; + + if (remove(m_pidfile) < 0) + return false; + + return true; +} diff --git a/utils/daemon.h b/utils/daemon.h new file mode 100644 index 00000000..f6a259a0 --- /dev/null +++ b/utils/daemon.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef DAEMON_H_ +#define DAEMON_H_ + +class Daemon +{ + +public: + static Daemon& Instance(); + ~Daemon() {} + + void run(const char* file); + void stop() { pidfile_close(); } + bool status() { return m_status; } + +private: + bool m_status; + const char* m_pidfile; + int m_pidfd; + + Daemon() {} + Daemon(const Daemon&); + Daemon& operator= (const Daemon&); + + bool pidfile_open(); + bool pidfile_close(); + +}; + +#endif // DAEMON_H_ diff --git a/utils/logger.cpp b/utils/logger.cpp new file mode 100644 index 00000000..9e7f04f3 --- /dev/null +++ b/utils/logger.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "logger.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static const char* AreaNames[Size_of_Area] = { "bas", "net", "bus" , "cyc" }; +static const char* LevelNames[Size_of_Level] = { "error", "event", "trace", "debug" }; + +LogMessage::LogMessage(const Area area, const Level level, const std::string text, const Status status) + : m_area(area), m_level(level), m_text(text), m_status(status) +{ + char time[24]; + struct timeval tv; + struct timezone tz; + struct tm* tm; + + gettimeofday(&tv, &tz); + tm = localtime(&tv.tv_sec); + + sprintf(&time[0], "%04d-%02d-%02d %02d:%02d:%02d.%03ld", + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000); + + m_time = std::string(time); +} + + + +void LogSink::addMessage(const LogMessage& message) +{ + LogMessage* tmp = new LogMessage(LogMessage(message)); + m_queue.add((tmp)); +} + +void* LogSink::run() +{ + while (1) { + LogMessage* message = m_queue.remove(); + if (message->getStatus() == LogMessage::End) { + delete message; + while (m_queue.size() == true) { + LogMessage* message = m_queue.remove(); + write(*message); + delete message; + } + return NULL; + } + + write(*message); + delete message; + } + return NULL; +} + + + +int LogConsole::m_numInstance = 0; + +void LogConsole::write(const LogMessage& message) const +{ + std::cout << message.getTime() << " [" + << AreaNames[(int)log2(message.getArea())] << " " + << LevelNames[message.getLevel()] << "] " + << message.getText() << std::endl; +} + + + +int LogFile::m_numInstance = 0; + +void LogFile::write(const LogMessage& message) const +{ + std::fstream file(m_filename.c_str(), std::ios::out | std::ios::app); + + if (file.is_open() == true) { + file << message.getTime() << " [" + << AreaNames[(int)log2(message.getArea())] << " " + << LevelNames[message.getLevel()] << "] " + << message.getText() << std::endl; + file.close(); + } +} + + + +LogInstance& LogInstance::Instance() +{ + static LogInstance instance; + return (instance); +} + +LogInstance::~LogInstance() +{ + while (m_sinks.empty() == false) + *this -= *(m_sinks.begin()); +} + +LogInstance& LogInstance::operator+= (LogSink* sink) +{ + sinkCI_t itEnd = m_sinks.end(); + sinkCI_t it = std::find(m_sinks.begin(), itEnd, sink); + + if (it == itEnd) + m_sinks.push_back(sink); + + return (*this); +} + +LogInstance& LogInstance::operator-= (const LogSink* sink) +{ + sinkCI_t itEnd = m_sinks.end(); + sinkCI_t it = std::find(m_sinks.begin(), itEnd, sink); + + if (it == itEnd) + return (*this); + + m_sinks.erase(it); + + delete (sink); + + return (*this); +} + +void LogInstance::log(const Area area, const Level level, const std::string& data, ...) +{ + if (m_running == true) { + char* tmp; + va_list ap; + va_start(ap, data); + + if (vasprintf(&tmp, data.c_str(), ap) != -1) { + std::string buffer(tmp); + m_messages.add(new LogMessage(LogMessage(area, level, buffer.c_str(), LogMessage::Run))); + } + + va_end(ap); + free(tmp); + } + +} + +void* LogInstance::run() +{ + m_running = true; + + while (m_running == true) { + LogMessage* message = m_messages.remove(); + + sinkCI_t iter = m_sinks.begin(); + + for (; iter != m_sinks.end(); ++iter) { + if (*iter != 0) { + + if (((*iter)->getAreas() & message->getArea() + && (*iter)->getLevel() >= message->getLevel()) + && message->getStatus() == LogMessage::Run) { + (*iter)->addMessage(*message); + } else if (message->getStatus() == LogMessage::End) { + (*iter)->addMessage(*message); + m_running = false; + } + + } + } + + delete message; + + } + return NULL; +} + +void LogInstance::stop() +{ + m_messages.add(new LogMessage(LogMessage(bas, error, "", LogMessage::End))); + // TODO: Improve this method + usleep(100000); +} diff --git a/utils/logger.h b/utils/logger.h new file mode 100644 index 00000000..c92cf49d --- /dev/null +++ b/utils/logger.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include "wqueue.h" +#include "thread.h" +#include +#include +#include +#include +#include + +enum Area { bas=1, net=2, bus=4, cyc=8, all=15, Size_of_Area=4 }; +enum Level { error=0, event, trace, debug, Size_of_Level }; + +class LogMessage +{ + +public: + enum Status { Run, End }; + + LogMessage(const Area area, const Level level, const std::string text, const Status status); + + ~LogMessage() {} + + LogMessage(const LogMessage& src) + : m_area(src.m_area), m_level(src.m_level), m_text(src.m_text), + m_status(src.m_status), m_time(src.m_time) {} + + void operator= (const LogMessage& src) + { m_area = src.m_area; m_level = src.m_level; m_text = src.m_text; + m_status = src.m_status; m_time = src.m_time; } + + Area getArea() const { return (m_area); } + Level getLevel() const { return(m_level); } + std::string getText() const { return (m_text.c_str()); } + Status getStatus() const { return (m_status); } + std::string getTime() const { return (m_time.c_str()); } + +private: + Area m_area; + Level m_level; + std::string m_text; + Status m_status; + std::string m_time; + +}; + +enum Type { Console, Logfile }; + +class LogSink : public Thread +{ + +public: + LogSink(const unsigned char areas, const Level level, const Type type, const char* name) + : m_areas(areas), m_level(level), m_type(type), m_name(name) {} + + virtual ~LogSink() {} + + void addMessage(const LogMessage& message); + + void* run(); + + unsigned char getAreas() const { return (m_areas); } + void setAreas(const unsigned char areas) { m_areas = areas; } + + Level getLevel() const { return (m_level); } + void setLevel(const Level level) { m_level = level; } + + Type getType() const { return (m_type); } + const char* getName() const { return (m_name.c_str()); } + +protected: + WQueue m_queue; + +private: + unsigned char m_areas; + Level m_level; + Type m_type; + std::string m_name; + + virtual void write(const LogMessage& message) const = 0; + +}; + +class LogConsole : public LogSink +{ + +public: + LogConsole(const unsigned char areas, const Level level, const char* name) + : LogSink(areas, level, Console, name), m_instance(++m_numInstance) + { this->start(name); } + + ~LogConsole() {} + +private: + const int m_instance; + static int m_numInstance; + + void write(const LogMessage& message) const; + +}; + +class LogFile : public LogSink +{ + +public: + LogFile(const unsigned char areas, const Level level, const char* name, const char* filename) + : LogSink(areas, level, Logfile, name), m_filename(filename), m_instance(++m_numInstance) + { this->start(name); } + + ~LogFile() {} + +private: + std::string m_filename; + const int m_instance; + static int m_numInstance; + + void write(const LogMessage& message) const; + +}; + +class LogInstance : public Thread +{ + +public: + static LogInstance& Instance(); + + ~LogInstance(); + + LogInstance& operator+= (LogSink* sink); + LogInstance& operator-= (const LogSink* sink); + + void log(const Area area, const Level level, const std::string& text, ...); + + int getNumberOfSinks() const { return(m_sinks.size()); } + LogSink* getSink(const int Index) const { return(m_sinks[Index]); } + + void* run(); + + void stop(); + +private: + LogInstance() {} + LogInstance(const LogInstance&); + LogInstance& operator= (const LogInstance&); + + typedef std::vector sink_t; + typedef std::vector::iterator sinkCI_t; + + sink_t m_sinks; + + WQueue m_messages; + + bool m_running; + +}; + +#endif // LOGGER_H_ diff --git a/utils/notify.h b/utils/notify.h new file mode 100644 index 00000000..93805f9d --- /dev/null +++ b/utils/notify.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef NOTIFY_H_ +#define NOTIFY_H_ + +#include +#include + +class Notify +{ + +public: + Notify() + { + int pipefd[2]; + int ret = pipe(pipefd); + + if (ret == 0) { + m_recvfd = pipefd[0]; + m_sendfd = pipefd[1]; + + fcntl(m_sendfd, F_SETFL, O_NONBLOCK); + } + + } + virtual ~Notify() { close(m_sendfd); close(m_recvfd); } + + int notifyFD() const { return m_recvfd; } + int notify() const { return write(m_sendfd,"1",1); } + +private: + int m_recvfd; + int m_sendfd; + +}; + +#endif // NOTIFY_H_ + + diff --git a/utils/tcpsocket.cpp b/utils/tcpsocket.cpp new file mode 100644 index 00000000..466ec60b --- /dev/null +++ b/utils/tcpsocket.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "tcpsocket.h" +#include +#include +#include + +TCPSocket::TCPSocket(int sfd, struct sockaddr_in* address) : m_sfd(sfd) +{ + char ip[17]; + inet_ntop(AF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1); + m_ip = ip; + m_port = ntohs(address->sin_port); +} + +bool TCPSocket::isValid() +{ + if (fcntl(m_sfd, F_GETFL) == -1) + return false; + else + return true; +} + + +int TCPListener::start() +{ + if (m_listening == true) + return 0; + + m_lfd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in address; + + memset(&address, 0, sizeof(address)); + + address.sin_family = AF_INET; + address.sin_port = htons(m_port); + + if (m_address.size() > 0) + inet_pton(AF_INET, m_address.c_str(), &(address.sin_addr)); + else + address.sin_addr.s_addr = INADDR_ANY; + + int optval = 1; + setsockopt(m_lfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + int result = bind(m_lfd, (struct sockaddr*) &address, sizeof(address)); + if (result != 0) + return result; + + result = listen(m_lfd, 5); + if (result != 0) + return result; + + m_listening = true; + return result; +} + +TCPSocket* TCPListener::newSocket() +{ + if (m_listening == false) + return NULL; + + struct sockaddr_in address; + socklen_t len = sizeof(address); + + memset(&address, 0, sizeof(address)); + + int sfd = accept(m_lfd, (struct sockaddr*) &address, &len); + + if (sfd < 0) + return NULL; + + return new TCPSocket(sfd, &address); +} + diff --git a/utils/tcpsocket.h b/utils/tcpsocket.h new file mode 100644 index 00000000..a8e9d80c --- /dev/null +++ b/utils/tcpsocket.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef TCPSOCKET_H_ +#define TCPSOCKET_H_ + +#include +#include +#include +#include + +class TCPSocket +{ + +public: + friend class TCPListener; + + ~TCPSocket() { close(m_sfd); } + + ssize_t recv(char* buffer, size_t len) { return read(m_sfd, buffer, len); } + ssize_t send(const char* buffer, size_t len) { return write(m_sfd, buffer, len); } + + int getPort() const { return m_port; } + std::string getIP() const { return m_ip; } + + int getFD() const { return m_sfd; } + bool isValid(); + +private: + int m_sfd; + int m_port; + std::string m_ip; + + TCPSocket(int sd, struct sockaddr_in* address); + +}; + +class TCPListener +{ + +public: + TCPListener(int port, std::string address) + : m_lfd(0), m_port(port), m_address(address), m_listening(false) {} + + ~TCPListener() { if (m_lfd > 0) {close(m_lfd);} } + + int start(); + TCPSocket* newSocket(); + + int getFD() const { return m_lfd; } + +private: + int m_lfd; + int m_port; + std::string m_address; + bool m_listening; + +}; + +#endif // TCPSOCKET_H_ + diff --git a/utils/thread.cpp b/utils/thread.cpp new file mode 100644 index 00000000..b1a2c908 --- /dev/null +++ b/utils/thread.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#include "thread.h" + +static void* runThread(void* arg) +{ + return ((Thread *)arg)->run(); +} + +Thread::Thread() : m_threadid(0), m_running(false), m_detached(false) {} + +Thread::~Thread() +{ + if (m_running == true && m_detached == false) + pthread_detach(m_threadid); + + if (m_running == true) + pthread_cancel(m_threadid); +} + +int Thread::start(const char* name) +{ + + int result = pthread_create(&m_threadid, NULL, runThread, this); + + if (result == 0) { + pthread_setname_np(m_threadid, name); + m_running = true; + } + + return result; +} + +int Thread::join() +{ + int result = -1; + + if (m_running == true) { + result = pthread_join(m_threadid, NULL); + + if (result == 0) + m_detached = false; + + } + + return result; +} + +int Thread::detach() +{ + int result = -1; + + if (m_running == true && m_detached == false) { + result = pthread_detach(m_threadid); + + if (result == 0) + m_detached = true; + + } + + return result; +} + +pthread_t Thread::self() +{ + return m_threadid; +} diff --git a/utils/thread.h b/utils/thread.h new file mode 100644 index 00000000..0abc32da --- /dev/null +++ b/utils/thread.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef THREAD_H_ +#define THREAD_H_ + +#include + +class Thread +{ + +public: + Thread(); + virtual ~Thread(); + + int start(const char* name); + int join(); + int detach(); + pthread_t self(); + + virtual void* run() = 0; + +private: + pthread_t m_threadid; + bool m_running; + bool m_detached; + +}; + +#endif // THREAD_H_ diff --git a/utils/wqueue.h b/utils/wqueue.h new file mode 100644 index 00000000..a3af1867 --- /dev/null +++ b/utils/wqueue.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) Roland Jax 2014 + * + * This file is part of ebus-daemon. + * + * ebus-daemon 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. + * + * ebus-daemon 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 ebus-daemon. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef WQUEUE_H_ +#define WQUEUE_H_ + +#include +#include + +template class WQueue +{ + +public: + WQueue() + { + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_condv, NULL); + } + + ~WQueue() + { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_condv); + } + + void add(T item) + { + pthread_mutex_lock(&m_mutex); + + m_queue.push_back(item); + + pthread_cond_signal(&m_condv); + pthread_mutex_unlock(&m_mutex); + } + + T remove() + { + pthread_mutex_lock(&m_mutex); + + while (m_queue.size() == 0) + pthread_cond_wait(&m_condv, &m_mutex); + + T item = m_queue.front(); + m_queue.pop_front(); + + pthread_mutex_unlock(&m_mutex); + + return item; + } + + int size() + { + pthread_mutex_lock(&m_mutex); + + int size = m_queue.size(); + + pthread_mutex_unlock(&m_mutex); + + return size; + } + +private: + std::list m_queue; + pthread_mutex_t m_mutex; + pthread_cond_t m_condv; + +}; + +#endif // WQUEUE_H_