diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5be27a --- /dev/null +++ b/.gitignore @@ -0,0 +1,247 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +[Xx]64/ +[Xx]86/ +[Bb]uild/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml + +# TODO: Un-comment the next line if you do not want to checkin +# your web deploy settings because they may include unencrypted +# passwords +#*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Microsoft Azure ApplicationInsights config file +ApplicationInsights.config + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# LightSwitch generated files +GeneratedArtifacts/ +ModelManifest.xml + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ +**/CodeDB +**/VisualGDBCache diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ca4cd4c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "src/knx"] + path = src/knx + url = https://github.com/thelsing/knx.git + branch = master diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -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/examples/knx-bme680/bme680.knxprod b/examples/knx-bme680/bme680.knxprod new file mode 100644 index 0000000..05f7fbe Binary files /dev/null and b/examples/knx-bme680/bme680.knxprod differ diff --git a/examples/knx-bme680/bme680.xml b/examples/knx-bme680/bme680.xml new file mode 100644 index 0000000..5239f18 --- /dev/null +++ b/examples/knx-bme680/bme680.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/knx-bme680/knx-bme680.ino b/examples/knx-bme680/knx-bme680.ino new file mode 100644 index 0000000..96de618 --- /dev/null +++ b/examples/knx-bme680/knx-bme680.ino @@ -0,0 +1,258 @@ +#include +#include + +// declare array of all groupobjects with their sizes in byte +GroupObject groupObjects[] +{ + GroupObject(2), + GroupObject(2), + GroupObject(2), + GroupObject(2), + GroupObject(2), + GroupObject(1), + GroupObject(2), + GroupObject(2), + GroupObject(1), + GroupObject(2) +} +; + +// create named references for easy access to group objects +GroupObject& goRawTemperature = groupObjects[0]; +GroupObject& goPressure = groupObjects[1]; +GroupObject& goRawHumidity = groupObjects[2]; +GroupObject& goGasResistance = groupObjects[3]; +GroupObject& goIaqEstimate = groupObjects[4]; +GroupObject& goIaqAccurace = groupObjects[5]; +GroupObject& goTemperature = groupObjects[6]; +GroupObject& goHumidity = groupObjects[7]; +GroupObject& goTriggerSample = groupObjects[8]; +GroupObject& goCo2Ppm = groupObjects[9]; + +#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // 360 minutes - 4 times a day + +// Helper functions declarations +void checkIaqSensorStatus(void); +void errLeds(void); +uint8_t* saveBme680State(uint8_t* buffer); +uint8_t* loadBme680State(uint8_t* buffer); +void triggerCallback(GroupObject& go); +void updateState(); + +///const uint8_t bsec_config_iaq[304] = +// { 0, 6, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 40, 0, 1, 0, 137, 65, 0, 63, 0, 0, 64, 63, 205, 204, 76, 62, 0, 0, 225, 68, 0, 192, 168, 71, 0, 0, 0, 0, 0, 80, 10, 90, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 2, 0, 0, 244, 1, 225, 0, 25, 10, 144, 1, 0, 0, 112, 65, 0, 0, 0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, 215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 51, 0, 9, 0, 10, 215, 163, 59, 205, 204, 204, 61, 225, 122, 148, 62, 41, 92, 15, 61, 0, 0, 0, 63, 0, 0, 0, 63, 154, 153, 89, 63, 154, 153, 25, 62, 1, 1, 0, 0, 128, 63, 6, 236, 81, 184, 61, 51, 51, 131, 64, 12, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 254, 0, 2, 1, 5, 48, 117, 100, 0, 44, 1, 151, 7, 132, 3, 197, 0, 144, 1, 64, 1, 64, 1, 48, 117, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, 98, 149, 0, 0 }; +const uint8_t bsec_config_iaq[304] = + { 0, 6, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 40, 0, 1, 0, 137, 65, 0, 63, 0, 0, 64, 63, 205, 204, 76, 62, 0, 0, 225, 68, 0, 168, 19, 73, 0, 0, 0, 0, 0, 80, 10, 90, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 2, 0, 0, 244, 1, 225, 0, 25, 10, 144, 1, 0, 0, 112, 65, 0, 0, 0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, 215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 51, 0, 9, 0, 10, 215, 163, 59, 205, 204, 204, 61, 225, 122, 148, 62, 41, 92, 15, 61, 0, 0, 0, 63, 0, 0, 0, 63, 154, 153, 89, 63, 154, 153, 25, 62, 1, 1, 0, 0, 128, 63, 6, 236, 81, 184, 61, 51, 51, 131, 64, 12, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 254, 0, 2, 1, 5, 48, 117, 100, 0, 44, 1, 151, 7, 132, 3, 197, 0, 144, 1, 64, 1, 64, 1, 48, 117, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, 253, 222, 0, 0 }; + + +// Create an object of the class Bsec +Bsec iaqSensor; +uint16_t stateUpdateCounter = 0; +uint8_t sendCounter = 0; +uint32_t cyclSend = 0; +bool trigger = false; + +// Entry point for the example +void setup(void) +{ + Serial.begin(115200); + delay(5000); + Serial.println("start"); + // register group objects + knx.registerGroupObjects(groupObjects, 10); + + // read adress table, association table, groupobject table and parameters from eeprom + knx.readMemory(); + + // register callback for reset GO + goTriggerSample.updateHandler = triggerCallback; + + + iaqSensor.begin(BME680_I2C_ADDR_SECONDARY, Wire); + checkIaqSensorStatus(); + + iaqSensor.setConfig(bsec_config_iaq); + checkIaqSensorStatus(); + + bsec_virtual_sensor_t sensorList[7] = { + BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + BSEC_OUTPUT_RAW_HUMIDITY, + BSEC_OUTPUT_RAW_GAS, + BSEC_OUTPUT_IAQ_ESTIMATE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, + }; + + knx.setSaveCallback(saveBme680State); + knx.setRestoreCallback(loadBme680State); + + if (knx.configured()) + { + cyclSend = knx.paramInt(0); + Serial.print("Zykl. send:"); + Serial.println(cyclSend); + } + + // start the framework. Will get wifi first. + knx.start(); + + iaqSensor.updateSubscription(sensorList, 7, BSEC_SAMPLE_RATE_LP); + checkIaqSensorStatus(); + String output = "Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%]"; + Serial.println(output); +} + +// Function that is looped forever +void loop(void) +{ + // don't delay here to much. Otherwise you might lose packages or mess up the timing with ETS + knx.loop(); + + // only run the application code if the device was configured with ETS + if(!knx.configured()) + return; + + if (iaqSensor.run()) + { + String output = String(millis()); + output += ", " + String(iaqSensor.rawTemperature); + output += ", " + String(iaqSensor.pressure); + output += ", " + String(iaqSensor.rawHumidity); + output += ", " + String(iaqSensor.gasResistance); + output += ", " + String(iaqSensor.iaqEstimate); + output += ", " + String(iaqSensor.iaqAccuracy); + output += ", " + String(iaqSensor.temperature); + output += ", " + String(iaqSensor.humidity); + Serial.println(output); + updateState(); + + if (sendCounter++ == cyclSend || trigger) + { + sendCounter = 0; + trigger = false; + + goRawTemperature.objectWrite(iaqSensor.rawTemperature); + goPressure.objectWrite(iaqSensor.pressure); + goRawHumidity.objectWrite(iaqSensor.rawHumidity); + goGasResistance.objectWrite(iaqSensor.gasResistance); + goIaqEstimate.objectWrite(iaqSensor.iaqEstimate); + goIaqAccurace.objectWrite(iaqSensor.iaqAccuracy); + goTemperature.objectWrite(iaqSensor.temperature); + goHumidity.objectWrite(iaqSensor.humidity); + } + } + else { + checkIaqSensorStatus(); + } +} + +// Helper function definitions +void checkIaqSensorStatus(void) +{ + if (iaqSensor.status != BSEC_OK) { + if (iaqSensor.status < BSEC_OK) { + String output = "BSEC error code : " + String(iaqSensor.status); + Serial.println(output); + for (;;) + errLeds(); /* Halt in case of failure */ + } + else { + String output = "BSEC warning code : " + String(iaqSensor.status); + Serial.println(output); + } + } + + if (iaqSensor.bme680Status != BME680_OK) { + if (iaqSensor.bme680Status < BME680_OK) { + String output = "BME680 error code : " + String(iaqSensor.bme680Status); + Serial.println(output); + for (;;) + errLeds(); /* Halt in case of failure */ + } + else { + String output = "BME680 warning code : " + String(iaqSensor.bme680Status); + Serial.println(output); + } + } +} + +void errLeds(void) +{ + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + delay(100); + digitalWrite(LED_BUILTIN, LOW); + delay(100); +} + +uint8_t* loadBme680State(uint8_t* buffer) +{ + // Existing state in EEPROM + Serial.println("Reading state from EEPROM"); + + for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) { + Serial.println(buffer[i], HEX); + } + + iaqSensor.setState(buffer); + checkIaqSensorStatus(); + return buffer + BSEC_MAX_STATE_BLOB_SIZE; +} + +uint8_t* saveBme680State(uint8_t* buffer) +{ + iaqSensor.getState(buffer); + checkIaqSensorStatus(); + + Serial.println("Writing state to EEPROM"); + + for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++) { + Serial.println(buffer[i], HEX); + } + return buffer + BSEC_MAX_STATE_BLOB_SIZE; +} + +void updateState(void) +{ + bool update = false; + if (stateUpdateCounter == 0) { + /* First state update when IAQ accuracy is >= 1 */ + if (iaqSensor.iaqAccuracy >= 3) { + update = true; + stateUpdateCounter++; + } + } + else { + /* Update every STATE_SAVE_PERIOD minutes */ + if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { + update = true; + stateUpdateCounter++; + } + } + + if (update) { + knx.writeMemory(); + } +} + +// callback from trigger-GO +void triggerCallback(GroupObject& go) +{ + Serial.println("trigger"); + Serial.println(go.objectReadBool()); + if (!go.objectReadBool()) + return; + + trigger = true; + /* We call bsec_update_subscription() in order to instruct BSEC to perform an extra measurement at the next + possible time slot + */ + Serial.println("Triggering ULP plus."); + bsec_virtual_sensor_t sensorList[1] = { + BSEC_OUTPUT_IAQ_ESTIMATE, + }; + + iaqSensor.updateSubscription(sensorList, 1, BSEC_SAMPLE_RATE_ULP_MEASUREMENT_ON_DEMAND); + checkIaqSensorStatus(); +} \ No newline at end of file diff --git a/examples/knx-demo/knx-demo-ip.knxprod b/examples/knx-demo/knx-demo-ip.knxprod new file mode 100644 index 0000000..801f3be Binary files /dev/null and b/examples/knx-demo/knx-demo-ip.knxprod differ diff --git a/examples/knx-demo/knx-demo-ip.xml b/examples/knx-demo/knx-demo-ip.xml new file mode 100644 index 0000000..da93378 --- /dev/null +++ b/examples/knx-demo/knx-demo-ip.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/knx-demo/knx-demo-tp.knxprod b/examples/knx-demo/knx-demo-tp.knxprod new file mode 100644 index 0000000..ccb1363 Binary files /dev/null and b/examples/knx-demo/knx-demo-tp.knxprod differ diff --git a/examples/knx-demo/knx-demo-tp.xml b/examples/knx-demo/knx-demo-tp.xml new file mode 100644 index 0000000..b7ae008 --- /dev/null +++ b/examples/knx-demo/knx-demo-tp.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/knx-demo/knx-demo.ino b/examples/knx-demo/knx-demo.ino new file mode 100644 index 0000000..80e5473 --- /dev/null +++ b/examples/knx-demo/knx-demo.ino @@ -0,0 +1,99 @@ +#include + +// declare array of all groupobjects with their sizes in byte +GroupObject groupObjects[] +{ + GroupObject(2), + GroupObject(2), + GroupObject(2), + GroupObject(1) +}; + +// create named references for easy access to group objects +GroupObject& goCurrent = groupObjects[0]; +GroupObject& goMax = groupObjects[1]; +GroupObject& goMin = groupObjects[2]; +GroupObject& goReset = groupObjects[3]; + +float currentValue = 0; +float maxValue = 0; +float minValue = RAND_MAX; +long lastsend = 0; + +void measureTemp() +{ + + long now = millis(); + if ((now - lastsend) < 2000) + return; + + lastsend = now; + int r = rand(); + currentValue = (r * 1.0) / (RAND_MAX * 1.0); + currentValue *= 100 * 100; + + // write new value to groupobject + goCurrent.objectWriteFloatDpt9(currentValue); + + if (currentValue > maxValue) + { + maxValue = currentValue; + goMax.objectWriteFloatDpt9(maxValue); + } + + if (currentValue < minValue) + { + minValue = currentValue; + goMin.objectWriteFloatDpt9(minValue); + } +} + +// callback from reset-GO +void resetCallback(GroupObject& go) +{ + if (go.objectReadBool()) + { + maxValue = 0; + minValue = 10000; + } +} + +void setup() +{ + Serial.begin(115200); + + randomSeed(millis()); + + // register group objects + knx.registerGroupObjects(groupObjects, 4); + // read adress table, association table, groupobject table and parameters from eeprom + knx.readMemory(); + + // register callback for reset GO + goReset.updateHandler = resetCallback; + + // print values of parameters if device is already configured + if (knx.configured()) + { + SerialDBG.print("Timeout: "); SerialDBG.println(knx.paramByte(0)); + SerialDBG.print("Zykl. senden: "); SerialDBG.println(knx.paramByte(1)); + SerialDBG.print("Min/Max senden: "); SerialDBG.println(knx.paramByte(2)); + SerialDBG.print("Aenderung senden: "); SerialDBG.println(knx.paramByte(3)); + SerialDBG.print("Abgleich: "); SerialDBG.println(knx.paramByte(4)); + } + + // start the framework. Will get wifi first. + knx.start(); +} + +void loop() +{ + // don't delay here to much. Otherwise you might lose packages or mess up the timing with ETS + knx.loop(); + + // only run the application code if the device was configured with ETS + if (!knx.configured()) + return; + + measureTemp(); +} diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..50c7755 --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=knx_esp +version=1.0.0 +author=Thomas Kunze +maintainer=Thomas Kunze +sentence=knx stack for esp8266 +paragraph= +category=Communication +url=https://github.com/thelsing/knx-esp +architectures=* +includes=knx_esp.h \ No newline at end of file diff --git a/src/arch_config.h b/src/arch_config.h new file mode 100644 index 0000000..044a407 --- /dev/null +++ b/src/arch_config.h @@ -0,0 +1,7 @@ +#pragma once + +#ifdef ARDUINO_ARCH_ESP8266 +#ifndef USE_STATES +#define USE_STATES +#endif +#endif \ No newline at end of file diff --git a/src/button.cpp b/src/button.cpp new file mode 100644 index 0000000..5b014a1 --- /dev/null +++ b/src/button.cpp @@ -0,0 +1,40 @@ +#include "button.h" +#include "state.h" +#include "knx_facade.h" + +#ifdef USE_STATES +unsigned long buttonTimestamp = 0; + +void buttonDown() +{ + buttonTimestamp = millis(); + attachInterrupt(knx.buttonPin(), buttonUp, RISING); +} +#endif + +void buttonUp() +{ +#ifdef USE_STATES + if (millis() - buttonTimestamp > 1000) + { + Serial.println("long button press"); + currentState->longButtonPress(); + } + else + { + Serial.println("short button press"); + currentState->shortButtonPress(); + } + attachInterrupt(knx.buttonPin(), buttonDown, FALLING); +#else if (knx.progMode()) + { + digitalWrite(knx.ledPin(), LOW); + knx.progMode(false); + } + else + { + digitalWrite(knx.ledPin(), HIGH); + knx.progMode(true); + } +#endif +} \ No newline at end of file diff --git a/src/button.h b/src/button.h new file mode 100644 index 0000000..4f921c1 --- /dev/null +++ b/src/button.h @@ -0,0 +1,8 @@ +#pragma once + +#include "arch_config.h" + +#ifdef USE_STATES +void buttonDown(); +#endif +void buttonUp(); \ No newline at end of file diff --git a/src/esp_platform.cpp b/src/esp_platform.cpp new file mode 100644 index 0000000..f68b4c0 --- /dev/null +++ b/src/esp_platform.cpp @@ -0,0 +1,174 @@ +#include "esp_platform.h" + +#ifdef ARDUINO_ARCH_ESP8266 +#include +#include +#include + +#include "knx/bits.h" + +EspPlatform::EspPlatform() +{ +} + +uint32_t EspPlatform::currentIpAddress() +{ + return WiFi.localIP(); +} + +uint32_t EspPlatform::currentSubnetMask() +{ + return WiFi.subnetMask(); +} + +uint32_t EspPlatform::currentDefaultGateway() +{ + return WiFi.gatewayIP(); +} + +void EspPlatform::macAddress(uint8_t * addr) +{ + wifi_get_macaddr(STATION_IF, addr); +} + +uint32_t EspPlatform::millis() +{ + return ::millis(); +} + +void EspPlatform::mdelay(uint32_t millis) +{ + delay(millis); +} + +void EspPlatform::restart() +{ + Serial.println("restart"); + ESP.reset(); +} + +void EspPlatform::fatalError() +{ + const int period = 200; + while (true) + { + if ((millis() % period) > (period / 2)) + digitalWrite(LED_BUILTIN, HIGH); + else + digitalWrite(LED_BUILTIN, LOW); + } +} + +void EspPlatform::setupMultiCast(uint32_t addr, uint16_t port) +{ + _mulitcastAddr = htonl(addr); + _mulitcastPort = port; + IPAddress mcastaddr(_mulitcastAddr); + + Serial.printf("setup multicast addr: %s port: %d ip: %s\n", mcastaddr.toString().c_str(), port, + WiFi.localIP().toString().c_str()); + uint8 result = _udp.beginMulticast(WiFi.localIP(), mcastaddr, port); + Serial.printf("result %d\n", result); +} + +void EspPlatform::closeMultiCast() +{ + _udp.stop(); +} + +bool EspPlatform::sendBytes(uint8_t * buffer, uint16_t len) +{ + //printHex("<- ",buffer, len); + int result = 0; + result = _udp.beginPacketMulticast(_mulitcastAddr, _mulitcastPort, WiFi.localIP()); + result = _udp.write(buffer, len); + result = _udp.endPacket(); + return true; +} + +int EspPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) +{ + int len = _udp.parsePacket(); + if (len == 0) + return 0; + + if (len > maxLen) + { + Serial.printf("udp buffer to small. was %d, needed %d\n", maxLen, len); + fatalError(); + } + + _udp.read(buffer, len); + //printHex("-> ", buffer, len); + return len; +} + +uint8_t * EspPlatform::getEepromBuffer(uint16_t size) +{ + EEPROM.begin(size); + return EEPROM.getDataPtr(); +} + +void EspPlatform::commitToEeprom() +{ + EEPROM.commit(); +} + +void EspPlatform::setupUart() +{ + Serial.begin(19200, SERIAL_8E1); + while (!Serial) ; +} + + +void EspPlatform::closeUart() +{ + Serial.end(); +} + + +int EspPlatform::uartAvailable() +{ + return Serial.available(); +} + + +size_t EspPlatform::writeUart(const uint8_t data) +{ + printHex(" 0) + printHex("p>", (uint8_t*)&val, 1); + return val; +} + + +size_t EspPlatform::readBytesUart(uint8_t *buffer, size_t length) +{ + size_t toRead = length; + uint8_t* pos = buffer; + while (toRead > 0) + { + size_t val = Serial.readBytes(pos, toRead); + pos += val; + toRead -= val; + } + + + printHex("p>", buffer, length); + return length; +} +#endif \ No newline at end of file diff --git a/src/esp_platform.h b/src/esp_platform.h new file mode 100644 index 0000000..a07361d --- /dev/null +++ b/src/esp_platform.h @@ -0,0 +1,49 @@ +#ifdef ARDUINO_ARCH_ESP8266 +#include "knx/platform.h" +#include +#include + +#define SerialDBG Serial + +class EspPlatform : public Platform +{ +public: + EspPlatform(); + + // ip stuff + uint32_t currentIpAddress(); + uint32_t currentSubnetMask(); + uint32_t currentDefaultGateway(); + void macAddress(uint8_t* addr); + + // basic stuff + uint32_t millis(); + void mdelay(uint32_t millis); + void restart(); + void fatalError(); + + //multicast + void setupMultiCast(uint32_t addr, uint16_t port); + void closeMultiCast(); + bool sendBytes(uint8_t* buffer, uint16_t len); + int readBytes(uint8_t* buffer, uint16_t maxLen); + + //uart + void setupUart(); + void closeUart(); + int uartAvailable(); + size_t writeUart(const uint8_t data); + size_t writeUart(const uint8_t *buffer, size_t size); + int readUart(); + size_t readBytesUart(uint8_t *buffer, size_t length); + + //memory + uint8_t* getEepromBuffer(uint16_t size); + void commitToEeprom(); +private: + uint32_t _mulitcastAddr; + uint16_t _mulitcastPort; + WiFiUDP _udp; +}; + +#endif \ No newline at end of file diff --git a/src/knx b/src/knx new file mode 160000 index 0000000..aaf6c27 --- /dev/null +++ b/src/knx @@ -0,0 +1 @@ +Subproject commit aaf6c275843ddcb541e8fdae4c8870ede1242370 diff --git a/src/knx_esp.h b/src/knx_esp.h new file mode 100644 index 0000000..18260d5 --- /dev/null +++ b/src/knx_esp.h @@ -0,0 +1,3 @@ +#pragma once + +#include "knx_facade.h" diff --git a/src/knx_facade.cpp b/src/knx_facade.cpp new file mode 100644 index 0000000..efe1e20 --- /dev/null +++ b/src/knx_facade.cpp @@ -0,0 +1,200 @@ +#include "knx_facade.h" +#include "state.h" +#include "button.h" +#include "led.h" +#include "nowifistate.h" + +#ifdef ARDUINO_ARCH_SAMD +SamdPlatform platform; +Bau07B0 bau(platform); +#else +EspPlatform platform; +Bau57B0 bau(platform); +#endif +KnxFacade knx(bau); + + +KnxFacade::KnxFacade(BauSystemB& bau) : _bau(bau) +{ + manufacturerId(0xfa); + _bau.addSaveRestore(this); +} + +bool KnxFacade::enabled() +{ + return _bau.enabled(); +} + +void KnxFacade::enabled(bool value) +{ + _bau.enabled(true); +} + +bool KnxFacade::progMode() +{ + return _bau.deviceObject().progMode(); +} + +void KnxFacade::progMode(bool value) +{ + _bau.deviceObject().progMode(value); +} + +bool KnxFacade::configured() +{ + return _bau.configured(); +} + +uint32_t KnxFacade::ledPin() +{ + return _ledPin; +} + +void KnxFacade::ledPin(uint32_t value) +{ + _ledPin = value; +} + +uint32_t KnxFacade::buttonPin() +{ + return _buttonPin; +} + +void KnxFacade::buttonPin(uint32_t value) +{ + _buttonPin = value; +} + +void KnxFacade::readMemory() +{ + _bau.readMemory(); +} + +void KnxFacade::writeMemory() +{ + _bau.writeMemory(); +} + +void KnxFacade::loop() +{ +#ifdef USE_STATES + if (currentState) + currentState->loop(); +#else + knxLoop(); +#endif +} + +void KnxFacade::knxLoop() +{ + _bau.loop(); +} + +void KnxFacade::registerGroupObjects(GroupObject* groupObjects, uint16_t count) +{ + _bau.groupObjectTable().groupObjects(groupObjects, count); +} + +void KnxFacade::manufacturerId(uint16_t value) +{ + _bau.deviceObject().manufacturerId(value); +} + +void KnxFacade::bauNumber(uint32_t value) +{ + _bau.deviceObject().bauNumber(value); +} + +void KnxFacade::orderNumber(const char* value) +{ + _bau.deviceObject().orderNumber(value); +} + +void KnxFacade::hardwareType(uint8_t* value) +{ + _bau.deviceObject().hardwareType(value); +} + +void KnxFacade::version(uint16_t value) +{ + _bau.deviceObject().version(value); +} + +void KnxFacade::start() +{ + pinMode(_ledPin, OUTPUT); + + pinMode(_buttonPin, INPUT_PULLUP); + +#ifdef USE_STATES + attachInterrupt(_buttonPin, buttonDown, FALLING); + switchToSate(noWifiState); + checkStates(); + _ticker.attach_ms(100, doLed); +#else + attachInterrupt(knx.buttonPin(), buttonUp, RISING); + enabled(true); +#endif +} + +uint8_t* KnxFacade::paramData(uint32_t addr) +{ + if (!_bau.configured()) + return nullptr; + + return _bau.parameters().data(addr); +} + +uint8_t KnxFacade::paramByte(uint32_t addr) +{ + if (!_bau.configured()) + return 0; + + return _bau.parameters().getByte(addr); +} + +uint16_t KnxFacade::paramWord(uint32_t addr) +{ + if (!_bau.configured()) + return 0; + + return _bau.parameters().getWord(addr); +} + +uint32_t KnxFacade::paramInt(uint32_t addr) +{ + if (!_bau.configured()) + return 0; + + return _bau.parameters().getInt(addr); +} + + +void KnxFacade::setSaveCallback(saveRestoreCallback func) +{ + _saveCallback = func; +} + + +void KnxFacade::setRestoreCallback(saveRestoreCallback func) +{ + _restoreCallback = func; +} + + +uint8_t* KnxFacade::save(uint8_t* buffer) +{ + if (_saveCallback != 0) + return _saveCallback(buffer); + + return buffer; +} + + +uint8_t* KnxFacade::restore(uint8_t* buffer) +{ + if (_restoreCallback != 0) + return _restoreCallback(buffer); + + return buffer; +} diff --git a/src/knx_facade.h b/src/knx_facade.h new file mode 100644 index 0000000..6cd9fd1 --- /dev/null +++ b/src/knx_facade.h @@ -0,0 +1,66 @@ +#pragma once + +#include "arch_config.h" + +#ifdef ARDUINO_ARCH_SAMD +#include "samd_platform.h" +#include "knx/bau07B0.h" +#endif + +#ifdef ARDUINO_ARCH_ESP8266 +#include +#include "esp_platform.h" +#include "knx/bau57B0.h" +#endif + +#ifdef USE_STATES +class RunningState; +#endif + +typedef uint8_t* (*saveRestoreCallback)(uint8_t* buffer); + +class KnxFacade : private SaveRestore +{ +public: + KnxFacade(BauSystemB& bau); + bool enabled(); + void enabled(bool value); + bool progMode(); + void progMode(bool value); + bool configured(); + uint32_t ledPin(); + void ledPin(uint32_t value); + uint32_t buttonPin(); + void buttonPin(uint32_t value); + void readMemory(); + void writeMemory(); + void loop(); + void knxLoop(); + void registerGroupObjects(GroupObject* groupObjects, uint16_t count); + void manufacturerId(uint16_t value); + void bauNumber(uint32_t value); + void orderNumber(const char* value); + void hardwareType(uint8_t* value); + void version(uint16_t value); + void start(); + void setSaveCallback(saveRestoreCallback func); + void setRestoreCallback(saveRestoreCallback func); + uint8_t* paramData(uint32_t addr); + uint8_t paramByte(uint32_t addr); + uint16_t paramWord(uint32_t addr); + uint32_t paramInt(uint32_t addr); +private: + BauSystemB& _bau; + uint32_t _ledPin = 16; + uint32_t _buttonPin = 0; +#ifdef USE_STATES + Ticker _ticker; +#endif + saveRestoreCallback _saveCallback = 0; + saveRestoreCallback _restoreCallback = 0; + + uint8_t* save(uint8_t* buffer); + uint8_t* restore(uint8_t* buffer); +}; + +extern KnxFacade knx; \ No newline at end of file diff --git a/src/knx_facade_samd.cpp b/src/knx_facade_samd.cpp new file mode 100644 index 0000000..db2e2f4 --- /dev/null +++ b/src/knx_facade_samd.cpp @@ -0,0 +1,174 @@ +#include "knx_facade.h" +#if 0 +KnxFacade knx; + + +#define SerialDBG SerialUSB + +void buttonUp(); +long buttonTimestamp = 0; +void buttonDown() +{ + buttonTimestamp = millis(); + attachInterrupt(knx.buttonPin(), buttonUp, RISING); +} + +void buttonUp() +{ + // keep short/long for now + if (millis() - buttonTimestamp > 1000) + { + SerialDBG.println("long button press"); + } + else + { + SerialDBG.println("short button press"); + } + + if (knx.progMode()) + { + digitalWrite(knx.ledPin(), LOW); + knx.progMode(false); + } + else + { + digitalWrite(knx.ledPin(), HIGH); + knx.progMode(true); + } + + attachInterrupt(knx.buttonPin(), buttonDown, FALLING); +} + +KnxFacade::KnxFacade() : _bau(_platform) +{ + manufacturerId(0xfa); +} + +bool KnxFacade::enabled() +{ + return _bau.enabled(); +} + +void KnxFacade::enabled(bool value) +{ + _bau.enabled(true); +} + +bool KnxFacade::progMode() +{ + return _bau.deviceObject().progMode(); +} + +void KnxFacade::progMode(bool value) +{ + _bau.deviceObject().progMode(value); +} + +bool KnxFacade::configured() +{ + return _bau.configured(); +} + +uint32_t KnxFacade::ledPin() +{ + return _ledPin; +} + +void KnxFacade::ledPin(uint32_t value) +{ + _ledPin = value; +} + +uint32_t KnxFacade::buttonPin() +{ + return _buttonPin; +} + +void KnxFacade::buttonPin(uint32_t value) +{ + _buttonPin = value; +} + +void KnxFacade::readMemory() +{ + _bau.readMemory(); +} + +void KnxFacade::loop() +{ + _bau.loop(); +} + +void KnxFacade::registerGroupObjects(GroupObject* groupObjects, uint16_t count) +{ + _bau.groupObjectTable().groupObjects(groupObjects, count); +} + +void KnxFacade::manufacturerId(uint16_t value) +{ + _bau.deviceObject().manufacturerId(value); +} + +void KnxFacade::bauNumber(uint32_t value) +{ + _bau.deviceObject().bauNumber(value); +} + +void KnxFacade::orderNumber(const char* value) +{ + _bau.deviceObject().orderNumber(value); +} + +void KnxFacade::hardwareType(uint8_t* value) +{ + _bau.deviceObject().hardwareType(value); +} + +void KnxFacade::version(uint16_t value) +{ + _bau.deviceObject().version(value); +} + +void KnxFacade::start() +{ + pinMode(_ledPin, OUTPUT); + + pinMode(_buttonPin, INPUT_PULLUP); + attachInterrupt(_buttonPin, buttonDown, FALLING); + enabled(true); +} + +uint8_t* KnxFacade::paramData(uint32_t addr) +{ + if (!_bau.configured()) + return nullptr; + + return _bau.parameters().data(addr); +} + +uint8_t KnxFacade::paramByte(uint32_t addr) +{ + if (!_bau.configured()) + return 0; + + return _bau.parameters().getByte(addr); +} + +uint16_t KnxFacade::paramWord(uint32_t addr) +{ + if (!_bau.configured()) + return 0; + + return _bau.parameters().getWord(addr); +} + +uint32_t KnxFacade::paramInt(uint32_t addr) +{ + if (!_bau.configured()) + return 0; + + return _bau.parameters().getInt(addr); +} + + +#endif \ No newline at end of file diff --git a/src/led.cpp b/src/led.cpp new file mode 100644 index 0000000..41030f2 --- /dev/null +++ b/src/led.cpp @@ -0,0 +1,30 @@ +#include "led.h" +#include "knx_facade.h" +#include "state.h" + +#ifdef USE_STATES +void doLed() +{ + if (!currentState) + return; + + if (!currentState->ledOn()) + { + digitalWrite(knx.ledPin(), HIGH); + return; + } + + unsigned int period = currentState->blinkPeriod(); + + if (!currentState->ledBlink() || period == 0) + { + digitalWrite(knx.ledPin(), LOW); + return; + } + + if ((millis() % period) > (period / 2)) + digitalWrite(knx.ledPin(), HIGH); + else + digitalWrite(knx.ledPin(), LOW); +} +#endif \ No newline at end of file diff --git a/src/led.h b/src/led.h new file mode 100644 index 0000000..fadcac6 --- /dev/null +++ b/src/led.h @@ -0,0 +1,7 @@ +#pragma once + +#include "arch_config.h" + +#ifdef USE_STATES +void doLed(); +#endif \ No newline at end of file diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp new file mode 100644 index 0000000..229f4c0 --- /dev/null +++ b/src/linux_platform.cpp @@ -0,0 +1,279 @@ +#include "linux_platform.h" +#ifdef __linux__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "knx/device_object.h" +#include "knx/address_table_object.h" +#include "knx/association_table_object.h" +#include "knx/group_object_table_object.h" +#include "knx/application_program_object.h" +#include "knx/ip_parameter_object.h" + +LinuxPlatform::LinuxPlatform() +{ + doMemoryMapping(); +} + +uint32_t LinuxPlatform::currentIpAddress() +{ + return 0; +} + +uint32_t LinuxPlatform::currentSubnetMask() +{ + return 0; +} + +uint32_t LinuxPlatform::currentDefaultGateway() +{ + return 0; +} + +uint32_t LinuxPlatform::millis() +{ + struct timespec spec; + + clock_gettime(CLOCK_MONOTONIC, &spec); + return spec.tv_sec * 1000 + round(spec.tv_nsec / 1.0e6); +} + +void LinuxPlatform::mdelay(uint32_t millis) +{ + struct timespec ts; + ts.tv_sec = millis / 1000; + ts.tv_nsec = (millis % 1000) * 1000000; + nanosleep(&ts, NULL); +} + +void LinuxPlatform::macAddress(uint8_t* data) +{ + // hardcode some address + data[0] = 0x08; + data[1] = 0x00; + data[2] = 0x27; + data[3] = 0x6c; + data[4] = 0xa8; + data[5] = 0x2a; +} + +void LinuxPlatform::restart() +{ + // do nothing +} + +void LinuxPlatform::fatalError() +{ + printf("A fatal error occured. Stopping.\n"); + while (true) + sleep(1); +} + +void LinuxPlatform::setupMultiCast(uint32_t addr, uint16_t port) +{ + _multicastAddr = addr; + _port = port; + + struct ip_mreq command; + uint32_t loop = 1; + + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = htons(port); + + _socketFd = socket(AF_INET, SOCK_DGRAM, 0); + if (_socketFd == -1) { + perror("socket()"); + fatalError(); + } + + /* Mehr Prozessen erlauben, denselben Port zu nutzen */ + loop = 1; + if (setsockopt(_socketFd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0) + { + perror("setsockopt:SO_REUSEADDR"); + fatalError(); + } + + if (bind(_socketFd, (struct sockaddr *)&sin, sizeof(sin)) < 0) + { + perror("bind"); + fatalError(); + } + + /* Broadcast auf dieser Maschine zulassen */ + loop = 1; + if (setsockopt(_socketFd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) + { + perror("setsockopt:IP_MULTICAST_LOOP"); + fatalError(); + } + + /* Join the broadcast group: */ + command.imr_multiaddr.s_addr = htonl(addr); + command.imr_interface.s_addr = htonl(INADDR_ANY); + + if (setsockopt(_socketFd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0) + { + perror("setsockopt:IP_ADD_MEMBERSHIP"); + fatalError(); + } + + uint32_t flags = fcntl(_socketFd, F_GETFL); + flags |= O_NONBLOCK; + fcntl(_socketFd, F_SETFL, flags); +} + +void LinuxPlatform::closeMultiCast() +{ + struct ip_mreq command; + command.imr_multiaddr.s_addr = htonl(_multicastAddr); + command.imr_interface.s_addr = htonl(INADDR_ANY); + + if (setsockopt(_socketFd, + IPPROTO_IP, + IP_DROP_MEMBERSHIP, + &command, sizeof(command)) < 0) { + perror("setsockopt:IP_DROP_MEMBERSHIP"); + } + close(_socketFd); +} + +bool LinuxPlatform::sendBytes(uint8_t* buffer, uint16_t len) +{ + struct sockaddr_in address = { 0 }; + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(_multicastAddr); + address.sin_port = htons(_port); + + ssize_t retVal = 0; + do + { + retVal = sendto(_socketFd, buffer, len, 0, (struct sockaddr *) &address, sizeof(address)); + if (retVal == -1) + { + if (errno != EAGAIN && errno != EWOULDBLOCK) + return false; + } + } while (retVal == -1); + return true; +} + +int LinuxPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) +{ + uint32_t sin_len; + struct sockaddr_in sin; + + sin_len = sizeof(sin); + ssize_t len = recvfrom(_socketFd, buffer, maxLen, 0, (struct sockaddr *) &sin, &sin_len); + return len; +} + +uint8_t * LinuxPlatform::getEepromBuffer(uint16_t size) +{ + return _mappedFile + 2; +} + +void LinuxPlatform::commitToEeprom() +{ + fsync(_fd); +} + +#define FLASHSIZE 0x10000 +void LinuxPlatform::doMemoryMapping() +{ + _fd = open("flash.bin", O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IROTH); + if (_fd < 0) + { + perror("Error in file opening"); + //exit(-1); + } + + struct stat st; + uint32_t ret = fstat(_fd, &st); + if (ret < 0) + { + perror("Error in fstat"); + //exit(-1); + } + + size_t len_file = st.st_size; + if (len_file < FLASHSIZE) + { + if (ftruncate(_fd, FLASHSIZE) != 0) + { + perror("Error extending file"); + //exit(-1); + } + len_file = FLASHSIZE; + } + unsigned char* addr = (unsigned char*)mmap(NULL, len_file, PROT_READ | PROT_WRITE, MAP_SHARED, _fd, 0); + if (addr[0] != 0xAF || addr[1] != 0xFE) + { + memset(addr, 0, FLASHSIZE); + addr[0] = 0xAF; + addr[1] = 0xFE; + } + + if (addr == MAP_FAILED) + { + perror("Error in mmap"); + //exit(-1); + } + _mappedFile = addr; +} + +size_t LinuxPlatform::readBytesUart(uint8_t *buffer, size_t length) +{ + return 0; +} + + +int LinuxPlatform::readUart() +{ + return -1; +} + + +size_t LinuxPlatform::writeUart(const uint8_t *buffer, size_t size) +{ + return 0; +} + + +size_t LinuxPlatform::writeUart(const uint8_t data) +{ + return 0; +} + + +int LinuxPlatform::uartAvailable() +{ + return 0; +} + + +void LinuxPlatform::closeUart() +{ +} + + +void LinuxPlatform::setupUart() +{ +} +#endif \ No newline at end of file diff --git a/src/linux_platform.h b/src/linux_platform.h new file mode 100644 index 0000000..710b9fa --- /dev/null +++ b/src/linux_platform.h @@ -0,0 +1,51 @@ +#pragma once + +#ifdef __linux__ + +#include "knx/platform.h" + +class LinuxPlatform: public Platform +{ +public: + LinuxPlatform(); + + // ip stuff + uint32_t currentIpAddress(); + uint32_t currentSubnetMask(); + uint32_t currentDefaultGateway(); + void macAddress(uint8_t* addr); + + // basic stuff + uint32_t millis(); + void mdelay(uint32_t millis); + void restart(); + void fatalError(); + + //multicast + void setupMultiCast(uint32_t addr, uint16_t port); + void closeMultiCast(); + bool sendBytes(uint8_t* buffer, uint16_t len); + int readBytes(uint8_t* buffer, uint16_t maxLen); + + //uart + void setupUart(); + void closeUart(); + int uartAvailable(); + size_t writeUart(const uint8_t data); + size_t writeUart(const uint8_t *buffer, size_t size); + int readUart(); + size_t readBytesUart(uint8_t *buffer, size_t length); + + //memory + uint8_t* getEepromBuffer(uint16_t size); + void commitToEeprom(); +private: + uint32_t _multicastAddr; + uint16_t _port; + int _socketFd = -1; + void doMemoryMapping(); + uint8_t* _mappedFile; + int _fd; +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..d0094f0 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,116 @@ +#ifdef __linux__ + +#include "linux_platform.h" +#include "knx/bau57B0.h" +#include "knx/group_object_table_object.h" +#include +#include +#include + +LinuxPlatform platfrom; +Bau57B0 bau(platfrom); + +float currentValue = 0; +float maxValue = 0; +float minValue = RAND_MAX; +long lastsend = 0; + +GroupObject groupObjects[] +{ + GroupObject(2), + GroupObject(2), + GroupObject(2), + GroupObject(1) +}; +#define CURR groupObjects[0] +#define MAX groupObjects[1] +#define MIN groupObjects[2] +#define RESET groupObjects[3] + +void measureTemp() +{ + long now = platfrom.millis(); + if ((now - lastsend) < 2000) + return; + + lastsend = now; + int r = rand(); + currentValue = (r * 1.0) / (RAND_MAX * 1.0); + currentValue *= 100 * 100; + + CURR.objectWrite(currentValue); + + if (currentValue > maxValue) + { + maxValue = currentValue; + MAX.objectWrite(maxValue); + } + + if (currentValue < minValue) + { + minValue = currentValue; + MIN.objectWrite(minValue); + } +} + +void resetCallback(GroupObject& go) +{ + if (go.objectReadBool()) + { + maxValue = 0; + minValue = 10000; + } +} + +void appLoop() +{ + if (!bau.configured()) + return; + + measureTemp(); +} + +void setup() +{ + srand((unsigned int)time(NULL)); + bau.readMemory(); + + uint8_t hwType[] = { 0x0, 0x0, 0x8, 0x0, 0x0, 0x2 }; + GroupObjectTableObject& got(bau.groupObjectTable()); + got.groupObjects(groupObjects, 4); + + DeviceObject& devObj(bau.deviceObject()); + devObj.manufacturerId(0xfa); + devObj.bauNumber(0xdeadbeef); + devObj.orderNumber("Coolstuff"); + devObj.hardwareType(hwType); + devObj.version(0x0020); + + RESET.updateHandler = resetCallback; + + if (bau.deviceObject().induvidualAddress() == 0) + bau.deviceObject().progMode(true); + + if (bau.parameters().loadState() == LS_LOADED) + { + printf("Timeout: %d\n", bau.parameters().getWord(0)); + printf("Zykl. senden: %d\n", bau.parameters().getByte(2)); + printf("Min/Max senden: %d\n", bau.parameters().getByte(3)); + printf("Aenderung senden: %d\n", bau.parameters().getByte(4)); + printf("Abgleich %d\n", bau.parameters().getByte(5)); + } + bau.enabled(true); +} + +int main(int argc, char **argv) +{ + setup(); + + while (1) + { + bau.loop(); + appLoop(); + platfrom.mdelay(100); + } +} +#endif \ No newline at end of file diff --git a/src/nowifistate.cpp b/src/nowifistate.cpp new file mode 100644 index 0000000..22feeb1 --- /dev/null +++ b/src/nowifistate.cpp @@ -0,0 +1,39 @@ +#include "nowifistate.h" +#include "wpsstate.h" +#include "runningstate.h" + +#ifdef USE_STATES + +#include + +NoWifiState noWifiState = NoWifiState(); + +void NoWifiState::shortButtonPress() +{ + switchToSate(wpsState); +} + +void NoWifiState::longButtonPress() +{ + switchToSate(wpsState); +} + +void NoWifiState::enterState() +{ + WiFi.mode(WIFI_STA); + WiFi.begin("", ""); + while (WiFi.status() == WL_DISCONNECTED) + { + delay(500); + Serial.print("."); + } + + wl_status_t status = WiFi.status(); + if (status == WL_CONNECTED) + { + Serial.printf("\nConnected successful to SSID '%s'\n", WiFi.SSID().c_str()); + switchToSate(runningState); + } +} + +#endif \ No newline at end of file diff --git a/src/nowifistate.h b/src/nowifistate.h new file mode 100644 index 0000000..f64892e --- /dev/null +++ b/src/nowifistate.h @@ -0,0 +1,20 @@ +#pragma once + +#include "state.h" + +#ifdef USE_STATES + +class NoWifiState : public State +{ +public: + NoWifiState() : State(true, false, 0) + {} + virtual void shortButtonPress(); + virtual void longButtonPress(); + virtual void enterState(); + virtual const char* name() { return "NoWifi"; } +}; + +extern NoWifiState noWifiState; + +#endif \ No newline at end of file diff --git a/src/programmingmodestate.cpp b/src/programmingmodestate.cpp new file mode 100644 index 0000000..32ee313 --- /dev/null +++ b/src/programmingmodestate.cpp @@ -0,0 +1,28 @@ +#include "programmingmodestate.h" +#include "runningstate.h" +#include "knx_facade.h" + +#ifdef USE_STATES +ProgramModeState programModeState = ProgramModeState(); + +void ProgramModeState::enterState() +{ + knx.progMode(true); +} + +void ProgramModeState::leaveState() +{ + knx.progMode(false); +} + +void ProgramModeState::shortButtonPress() +{ + switchToSate(runningState); +} + +void ProgramModeState::loop() +{ + State::loop(); + knx.knxLoop(); +} +#endif \ No newline at end of file diff --git a/src/programmingmodestate.h b/src/programmingmodestate.h new file mode 100644 index 0000000..0167905 --- /dev/null +++ b/src/programmingmodestate.h @@ -0,0 +1,21 @@ +#pragma once + +#include "state.h" + +#ifdef USE_STATES + +class ProgramModeState : public State +{ +public: + ProgramModeState() : State(true, true, 200) + {} + virtual void enterState(); + virtual void leaveState(); + virtual void shortButtonPress(); + virtual void loop(); + virtual const char* name() { return "ProgramMode"; } +}; + +extern ProgramModeState programModeState; + +#endif \ No newline at end of file diff --git a/src/runningstate.cpp b/src/runningstate.cpp new file mode 100644 index 0000000..c97ef0a --- /dev/null +++ b/src/runningstate.cpp @@ -0,0 +1,43 @@ +#include "runningstate.h" +#include "programmingmodestate.h" +#include "wpsstate.h" +#include "knx_facade.h" + +#ifdef USE_STATES + +RunningState runningState = RunningState(); + +void RunningState::shortButtonPress() +{ + switchToSate(programModeState); +} + +void RunningState::longButtonPress() +{ + switchToSate(wpsState); +} + +void RunningState::enterState() +{ + if (_initialized) + return; + + knx.enabled(true); + _initialized = true; +} + +void RunningState::leaveState() +{ + if (nextState != &programModeState) + { + _initialized = false; + knx.enabled(false); + } +} + +void RunningState::loop() +{ + State::loop(); + knx.knxLoop(); +} +#endif \ No newline at end of file diff --git a/src/runningstate.h b/src/runningstate.h new file mode 100644 index 0000000..88d7b3e --- /dev/null +++ b/src/runningstate.h @@ -0,0 +1,21 @@ +#pragma once + +#include "state.h" +#ifdef USE_STATES +class RunningState : public State +{ +public: + RunningState() : State(false, false, 0) + {} + virtual void shortButtonPress(); + virtual void longButtonPress(); + virtual void enterState(); + virtual void leaveState(); + virtual void loop(); + virtual const char* name() { return "Running"; } +private: + bool _initialized = false; +}; + +extern RunningState runningState; +#endif \ No newline at end of file diff --git a/src/samd_platform.cpp b/src/samd_platform.cpp new file mode 100644 index 0000000..3e72a23 --- /dev/null +++ b/src/samd_platform.cpp @@ -0,0 +1,157 @@ +#include "samd_platform.h" + +#ifdef ARDUINO_ARCH_SAMD +#include + +#include +#include + +SamdPlatform::SamdPlatform() +{ +} + +uint32_t SamdPlatform::currentIpAddress() +{ + // not needed + return 0; +} + +uint32_t SamdPlatform::currentSubnetMask() +{ + // not needed + return 0; +} + +uint32_t SamdPlatform::currentDefaultGateway() +{ + // not needed + return 0; +} + +void SamdPlatform::macAddress(uint8_t * addr) +{ + // not needed +} + +uint32_t SamdPlatform::millis() +{ + return::millis(); +} + +void SamdPlatform::mdelay(uint32_t millis) +{ + delay(millis); +} + +void SamdPlatform::restart() +{ + SerialUSB.println("restart"); + NVIC_SystemReset(); +} + +void SamdPlatform::fatalError() +{ + const int period = 200; + while (true) + { + if ((millis() % period) > (period / 2)) + digitalWrite(LED_BUILTIN, HIGH); + else + digitalWrite(LED_BUILTIN, LOW); + } +} + +void SamdPlatform::setupMultiCast(uint32_t addr, uint16_t port) +{ + //not needed +} + +void SamdPlatform::closeMultiCast() +{ + //not needed +} + +bool SamdPlatform::sendBytes(uint8_t * buffer, uint16_t len) +{ + //not needed +} + +int SamdPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) +{ + //not needed + return 0; +} + +uint8_t * SamdPlatform::getEepromBuffer(uint16_t size) +{ + //EEPROM.begin(size); + if(size > EEPROM_EMULATION_SIZE) + fatalError(); + + return EEPROM.getDataPtr(); +} + +void SamdPlatform::commitToEeprom() +{ + EEPROM.commit(); +} + + +void SamdPlatform::setupUart() +{ + SerialKNX.begin(19200, SERIAL_8E1); + while (!SerialKNX) + ; +} + + +void SamdPlatform::closeUart() +{ + SerialKNX.end(); +} + + +int SamdPlatform::uartAvailable() +{ + return SerialKNX.available(); +} + + +size_t SamdPlatform::writeUart(const uint8_t data) +{ + //printHex(" 0) + // printHex("p>", (uint8_t*)&val, 1); + return val; +} + + +size_t SamdPlatform::readBytesUart(uint8_t *buffer, size_t length) +{ + size_t toRead = length; + uint8_t* pos = buffer; + while (toRead > 0) + { + size_t val = SerialKNX.readBytes(pos, toRead); + pos += val; + toRead -= val; + } + //printHex("p>", buffer, length); + return length; +} + +#endif \ No newline at end of file diff --git a/src/samd_platform.h b/src/samd_platform.h new file mode 100644 index 0000000..df7acdb --- /dev/null +++ b/src/samd_platform.h @@ -0,0 +1,50 @@ +#include "knx/platform.h" + +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_SAMD + +#define SerialDBG SerialUSB +#define SerialKNX Serial1 + +class SamdPlatform : public Platform +{ +public: + SamdPlatform(); + + // ip stuff + uint32_t currentIpAddress(); + uint32_t currentSubnetMask(); + uint32_t currentDefaultGateway(); + void macAddress(uint8_t* addr); + + // basic stuff + uint32_t millis(); + void mdelay(uint32_t millis); + void restart(); + void fatalError(); + + //multicast + void setupMultiCast(uint32_t addr, uint16_t port); + void closeMultiCast(); + bool sendBytes(uint8_t* buffer, uint16_t len); + int readBytes(uint8_t* buffer, uint16_t maxLen); + + //uart + virtual void setupUart(); + virtual void closeUart(); + virtual int uartAvailable(); + virtual size_t writeUart(const uint8_t data); + virtual size_t writeUart(const uint8_t *buffer, size_t size); + virtual int readUart(); + virtual size_t readBytesUart(uint8_t *buffer, size_t length); + + //memory + uint8_t* getEepromBuffer(uint16_t size); + void commitToEeprom(); +private: + uint32_t _mulitcastAddr; + uint16_t _mulitcastPort; +}; + +#endif \ No newline at end of file diff --git a/src/state.cpp b/src/state.cpp new file mode 100644 index 0000000..4199f46 --- /dev/null +++ b/src/state.cpp @@ -0,0 +1,57 @@ +#include "state.h" +#include "Arduino.h" + +#ifdef USE_STATES + +State* volatile currentState = 0; +State* volatile nextState = 0; + +void switchToSate(State& state) +{ + nextState = &state; +} + +void checkStates() +{ + if (!nextState) + return; + + if (nextState == currentState) + return; + + if (currentState) + { + printf("Leave %s\n", currentState->name()); + currentState->leaveState(); + } + + currentState = nextState; + + if (currentState) + { + printf("Enter %s\n", currentState->name()); + currentState->enterState(); + } +} + +bool State::ledOn() +{ + return _ledOn; +} + +bool State::ledBlink() +{ + return _ledBlink; +} + +unsigned int State::blinkPeriod() +{ + return _blinkPeriod; +} + +void State::loop() +{ + checkStates(); +} + +#endif \ No newline at end of file diff --git a/src/state.h b/src/state.h new file mode 100644 index 0000000..9b155b1 --- /dev/null +++ b/src/state.h @@ -0,0 +1,34 @@ +#pragma once +#include "arch_config.h" + +#ifdef USE_STATES + +class State +{ +public: + State(bool led, bool blink, int period) : + _ledOn(led), _ledBlink(blink), _blinkPeriod(period) + {} + virtual ~State() {} + bool ledOn(); + bool ledBlink(); + unsigned int blinkPeriod(); + virtual void shortButtonPress() {} + virtual void longButtonPress() {} + virtual void enterState() {} + virtual void leaveState() {} + virtual void loop(); + virtual const char* name() = 0; +private: + bool _ledOn; + bool _ledBlink; + int _blinkPeriod; +}; + +void switchToSate(State& state); +void checkStates(); + +extern State* volatile currentState; +extern State* volatile nextState; + +#endif \ No newline at end of file diff --git a/src/wpsstate.cpp b/src/wpsstate.cpp new file mode 100644 index 0000000..615f290 --- /dev/null +++ b/src/wpsstate.cpp @@ -0,0 +1,33 @@ +#include "arch_config.h" + +#ifdef USE_STATES +#include + +#include "wpsstate.h" +#include "runningstate.h" +#include "nowifistate.h" + +WpsState wpsState = WpsState(); + +void WpsState::enterState() +{ + //invalidate old wifi settings first + WiFi.begin("fobar", "a12"); + Serial.println("WPS config start"); + bool wpsSuccess = WiFi.beginWPSConfig(); + if (wpsSuccess) { + String newSSID = WiFi.SSID(); + if (newSSID.length() > 0) + { + Serial.printf("WPS finished. Connected successfull to SSID '%s'\n", newSSID.c_str()); + switchToSate(runningState); + } + else + { + Serial.printf("WPS failed."); + switchToSate(noWifiState); + } + } +} + +#endif diff --git a/src/wpsstate.h b/src/wpsstate.h new file mode 100644 index 0000000..3f985ab --- /dev/null +++ b/src/wpsstate.h @@ -0,0 +1,17 @@ +#pragma once + +#include "state.h" + +#ifdef USE_STATES +class WpsState : public State +{ +public: + WpsState() : State(true, true, 400) + {} + virtual void enterState(); + virtual const char* name() { return "Wps"; } +}; + +extern WpsState wpsState; + +#endif diff --git a/visualstudio/ClassDiagram.cd b/visualstudio/ClassDiagram.cd new file mode 100644 index 0000000..fa67e07 --- /dev/null +++ b/visualstudio/ClassDiagram.cd @@ -0,0 +1,95 @@ + + + + + + IBAAAAAAQACAEAIAABAAAAgAAAAAAAAAAAAAAABAAEA= + knx\address_table_object.h + + + + + + AIAAAAAAAACAAAIAgCAAAAAgABAEAAAAAAAQQABAAAA= + knx\application_program_object.h + + + + + + AAAAAAAAAACAAgIAABAAQAgAAAEAAAAAAAAAAABAAEA= + knx\association_table_object.h + + + + + + AAACACEAAAGCIAKAQCAgAACgCECAAEIgAEgAAgJAAAA= + knx\device_object.h + + + + + + AAAAAEAACACAAgIAAhAATAgACAAAAAAAAAAAAABAAAA= + knx\group_object_table_object.h + + + + + + AAAAAAAAAAAAAAAAACAAAAAgAAAAAAAAAAAAABBAAAA= + knx\interface_object.h + + + + + + AAIACIAAYACAAKIAAGAQCAAgWAIAAAAGAAAAAABgAIA= + knx\ip_parameter_object.h + + + + + + AAIACIACBACAAIIAAGAASAgwyAAAAAAAAgAAAAJgAAA= + knx\table_object.h + + + + + + sKoIAAAAQIIxC4gUUEAIAAACiQEgAjQUFCCA5yEAIBw= + knx\bau.h + + + + + + ABIAAFAgAgIwCoAAUiCCQIDAiEBgADQQACAAAAKQABw= + knx\bau57B0.h + + + + + + BACCIBAAICAAICgAAABAgAAQAAAAAAgAAADAEAAAAhA= + linux_platform.h + + + + + + AAAAAAAAAACAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + knx\save_restore.h + + + + + + AAACIBAAICAAIAAAAABAgAAAAAAAAAgAAADAEAAAAhA= + knx\platform.h + + + + \ No newline at end of file diff --git a/visualstudio/knx-bme680.vgdbproj b/visualstudio/knx-bme680.vgdbproj new file mode 100644 index 0000000..81da2fc --- /dev/null +++ b/visualstudio/knx-bme680.vgdbproj @@ -0,0 +1,340 @@ + + + Release + + + + Unknown + + + 58afeecd-06e2-4bb7-a13f-e1d5dbaed13f + true + true + ..\examples\knx-bme680 + basic_config_state_ulp_plus.ino + + + + knx-bme680.ino + + + + + + + + .. + ..\.. + + Output\$(PlatformName.defuse)\$(ConfigurationName.defuse) + false + + + + + + + + + + + + + Default + + + + COM5 + + 115200 + 8 + None + One + None + + + 0 + false + false + true + ASCII + + + 255 + 0 + 0 + 0 + + + 255 + 169 + 169 + 169 + + + 255 + 211 + 211 + 211 + + + 255 + 144 + 238 + 144 + + + 255 + 169 + 169 + 169 + + + + 16 + true + true + true + true + 0 + + LF + true + true + true + + + + true + + + + + True + + true + true + + Enabled + true + true + true + + true + + + + false + + apiModeling.google.GTest + core.builtin.BuiltinFunctions + core.builtin.NoReturnFunctions + core.CallAndMessage + core.DivideZero + core.DynamicTypePropagation + core.NonnilStringConstants + core.NonNullParamChecker + core.NullDereference + core.StackAddressEscape + core.UndefinedBinaryOperatorResult + core.uninitialized.ArraySubscript + core.uninitialized.Assign + core.uninitialized.Branch + core.uninitialized.CapturedBlockVariable + core.uninitialized.UndefReturn + core.VLASize + cplusplus.NewDelete + cplusplus.NewDeleteLeaks + cplusplus.SelfAssignment + deadcode.DeadStores + nullability.NullPassedToNonnull + nullability.NullReturnedFromNonnull + security.insecureAPI.getpw + security.insecureAPI.gets + security.insecureAPI.mkstemp + security.insecureAPI.mktemp + security.insecureAPI.UncheckedReturn + security.insecureAPI.vfork + unix.API + unix.cstring.BadSizeArg + unix.cstring.NullArg + unix.Malloc + unix.MallocSizeof + unix.MismatchedDeallocator + unix.StdCLibraryFunctions + unix.Vfork + + + -analyzer-store=region + -analyzer-opt-analyze-nested-blocks + -analyzer-eagerly-assume + + + + + + NodeMCU 1 0 (ESP-12E Module) + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + false + 0 + + + gdbstub + + 74880 + 115200 + 50 + !DTR;RTS;SLEEP;DTR;!RTS;SLEEP;!DTR;SLEEP + Enabled + false + + size4M + freq40M + QIO + + + + true + Disabled + 0 + false + false + true + false + false + + _estack + 0 + false + true + + + esp8266:esp8266:nodemcuv2 + COM5 + + + + CpuFrequency + 80 + + + VTable + flash + + + FlashSize + 4M1M + + + LwIPVariant + v2mss536 + + + Debug + Serial + + + DebugLevel + None____ + + + FlashErase + none + + + UploadSpeed + 115200 + + + + Sketch + + + + Arduino Genuino Zero (Native USB Port) + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + false + 0 + + + true + Auto + 0 + false + false + true + false + false + + _estack + 0 + false + true + + + arduino:samd:arduino_zero_native + + + + Sketch + + + + + \ No newline at end of file diff --git a/visualstudio/knx-demo.vgdbproj b/visualstudio/knx-demo.vgdbproj new file mode 100644 index 0000000..0dc1c7e --- /dev/null +++ b/visualstudio/knx-demo.vgdbproj @@ -0,0 +1,343 @@ + + + Debug + + + + Unknown + + + 6165cd6a-91a4-49fa-977a-48f22086ca8e + true + true + ..\examples\knx-demo + Sketch.ino + + + + knx-demo.ino + + + + + + + + ..\.. + + Output\$(PlatformName.defuse)\$(ConfigurationName.defuse) + true + + + + + + + + + + + + + Default + + + + COM9 + + 115200 + 8 + None + One + None + + + 0 + false + false + false + ASCII + + + 255 + 0 + 0 + 0 + + + 255 + 169 + 169 + 169 + + + 255 + 211 + 211 + 211 + + + 255 + 144 + 238 + 144 + + + 255 + 169 + 169 + 169 + + + + 16 + true + true + true + true + 0 + + LF + false + true + true + + + + true + + + + + True + + true + true + + Enabled + true + true + true + + true + + + + false + + apiModeling.google.GTest + core.builtin.BuiltinFunctions + core.builtin.NoReturnFunctions + core.CallAndMessage + core.DivideZero + core.DynamicTypePropagation + core.NonnilStringConstants + core.NonNullParamChecker + core.NullDereference + core.StackAddressEscape + core.UndefinedBinaryOperatorResult + core.uninitialized.ArraySubscript + core.uninitialized.Assign + core.uninitialized.Branch + core.uninitialized.CapturedBlockVariable + core.uninitialized.UndefReturn + core.VLASize + cplusplus.NewDelete + cplusplus.NewDeleteLeaks + cplusplus.SelfAssignment + deadcode.DeadStores + nullability.NullPassedToNonnull + nullability.NullReturnedFromNonnull + security.insecureAPI.getpw + security.insecureAPI.gets + security.insecureAPI.mkstemp + security.insecureAPI.mktemp + security.insecureAPI.UncheckedReturn + security.insecureAPI.vfork + unix.API + unix.cstring.BadSizeArg + unix.cstring.NullArg + unix.Malloc + unix.MallocSizeof + unix.MismatchedDeallocator + unix.StdCLibraryFunctions + unix.Vfork + + + -analyzer-store=region + -analyzer-opt-analyze-nested-blocks + -analyzer-eagerly-assume + + + + + + NodeMCU 1 0 (ESP-12E Module) + + + + + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + false + 0 + + + gdbstub + + 74880 + 115200 + 50 + !DTR;RTS;SLEEP;DTR;!RTS;SLEEP;!DTR;SLEEP + Auto + false + + size4M + freq40M + QIO + + + + true + Disabled + 0 + false + false + true + false + false + + _estack + 0 + false + true + + + esp8266:esp8266:nodemcuv2 + COM7 + + + + CpuFrequency + 80 + + + VTable + flash + + + FlashSize + 4M1M + + + LwIPVariant + v2mss536 + + + Debug + Disabled + + + DebugLevel + None____ + + + FlashErase + none + + + UploadSpeed + 115200 + + + + Sketch + + + + Arduino Genuino Zero (Native USB Port) + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + false + 0 + + + true + Auto + 0 + false + false + true + false + false + + _estack + 0 + false + true + + + arduino:samd:arduino_zero_native + + + + Sketch + + + + + \ No newline at end of file diff --git a/visualstudio/knx-linux-Debug.vgdbsettings b/visualstudio/knx-linux-Debug.vgdbsettings new file mode 100644 index 0000000..d3e6100 --- /dev/null +++ b/visualstudio/knx-linux-Debug.vgdbsettings @@ -0,0 +1,148 @@ + + + Release + + + + RemoteUnix + + + localhost + LinuxSubsystem + Linux + + + false + + localhost + LinuxSubsystem + Linux + + $(ProjectDir) + /home/tkunze/vgdb/knx-linux + + *.cpp + *.h + *.hpp + *.c + *.cc + *.cxx + *.mak + Makefile + *.txt + *.cmake + CMakeLists.txt + *.cmake + + true + true + + true + true + + false + false + false + false + false + $(ProjectDir) + + + + com.sysprogs.toolchain.default-gcc + + 0 + + + knx-linux.vcxproj + 0 + true + + + + + + + + + + + + + Default + + + + true + + + + + Unknown + + true + false + + + + + false + + + + + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + false + 0 + + + + + + LANG + en_US.UTF-8 + + + + + $(TargetPath) + 2000 + + + false + Local + false + false + Auto + true + false + + \ No newline at end of file diff --git a/visualstudio/knx-linux-Release.vgdbsettings b/visualstudio/knx-linux-Release.vgdbsettings new file mode 100644 index 0000000..d3e6100 --- /dev/null +++ b/visualstudio/knx-linux-Release.vgdbsettings @@ -0,0 +1,148 @@ + + + Release + + + + RemoteUnix + + + localhost + LinuxSubsystem + Linux + + + false + + localhost + LinuxSubsystem + Linux + + $(ProjectDir) + /home/tkunze/vgdb/knx-linux + + *.cpp + *.h + *.hpp + *.c + *.cc + *.cxx + *.mak + Makefile + *.txt + *.cmake + CMakeLists.txt + *.cmake + + true + true + + true + true + + false + false + false + false + false + $(ProjectDir) + + + + com.sysprogs.toolchain.default-gcc + + 0 + + + knx-linux.vcxproj + 0 + true + + + + + + + + + + + + + Default + + + + true + + + + + Unknown + + true + false + + + + + false + + + + + + + + + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + true + false + None + false + false + main + true + false + false + false + 0 + + + + + + LANG + en_US.UTF-8 + + + + + $(TargetPath) + 2000 + + + false + Local + false + false + Auto + true + false + + \ No newline at end of file diff --git a/visualstudio/knx-linux.vcxproj b/visualstudio/knx-linux.vcxproj new file mode 100644 index 0000000..1e732b4 --- /dev/null +++ b/visualstudio/knx-linux.vcxproj @@ -0,0 +1,131 @@ + + + + + Debug + VisualGDB + + + Release + VisualGDB + + + + 15.0 + {819E55F9-05A8-454D-B771-4A99F775DD87} + + + + + GCC + + + + GCC + + + com.sysprogs.toolchain.default-gcc + + + + + + + + + + + + localhost-lxss + + + localhost-lxss + + + + /usr/include/x86_64-linux-gnu;%(ClCompile.AdditionalIncludeDirectories) + + + + + + + + /usr/include/x86_64-linux-gnu;%(ClCompile.AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/visualstudio/knx-linux.vcxproj.filters b/visualstudio/knx-linux.vcxproj.filters new file mode 100644 index 0000000..5cfbad1 --- /dev/null +++ b/visualstudio/knx-linux.vcxproj.filters @@ -0,0 +1,217 @@ + + + + + {7612a532-0bb6-4a82-917a-48cfa6410e4f} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {842f6d29-354f-47a8-bfd9-0fccf0ddf144} + h;hpp;hxx;hm;inl;inc;xsd + + + {c46b2f8f-4105-4638-af5c-09a641257065} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {c818187b-4f9f-4ee9-86c3-d26e56e49bf9} + *.vgdbsettings + + + {169b6f5b-b022-4422-ace2-819bf2f5e883} + + + {4054619f-7b60-405c-96e8-311c464cf8de} + + + + + + VisualGDB settings + + + VisualGDB settings + + + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + Header files\knx + + + + + Source files\knx + + + Source files + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + Source files\knx + + + \ No newline at end of file diff --git a/visualstudio/knx.sln b/visualstudio/knx.sln new file mode 100644 index 0000000..69aad4e --- /dev/null +++ b/visualstudio/knx.sln @@ -0,0 +1,57 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2050 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "knx-linux", "knx-linux.vcxproj", "{819E55F9-05A8-454D-B771-4A99F775DD87}" +EndProject +Project("{803FD0C6-D64E-4E16-9DC3-1DAEC859A3D2}") = "knx-bme680", "knx-bme680.vgdbproj", "{58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}" +EndProject +Project("{803FD0C6-D64E-4E16-9DC3-1DAEC859A3D2}") = "knx-demo", "knx-demo.vgdbproj", "{6165CD6A-91A4-49FA-977A-48F22086CA8E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Arduino Genuino Zero (Native USB Port) = Debug|Arduino Genuino Zero (Native USB Port) + Debug|NodeMCU 1 0 (ESP-12E Module) = Debug|NodeMCU 1 0 (ESP-12E Module) + Debug|VisualGDB = Debug|VisualGDB + Release|Arduino Genuino Zero (Native USB Port) = Release|Arduino Genuino Zero (Native USB Port) + Release|NodeMCU 1 0 (ESP-12E Module) = Release|NodeMCU 1 0 (ESP-12E Module) + Release|VisualGDB = Release|VisualGDB + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {819E55F9-05A8-454D-B771-4A99F775DD87}.Debug|Arduino Genuino Zero (Native USB Port).ActiveCfg = Debug|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Debug|NodeMCU 1 0 (ESP-12E Module).ActiveCfg = Debug|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Debug|VisualGDB.ActiveCfg = Debug|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Debug|VisualGDB.Build.0 = Debug|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Release|Arduino Genuino Zero (Native USB Port).ActiveCfg = Release|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Release|NodeMCU 1 0 (ESP-12E Module).ActiveCfg = Release|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Release|VisualGDB.ActiveCfg = Release|VisualGDB + {819E55F9-05A8-454D-B771-4A99F775DD87}.Release|VisualGDB.Build.0 = Release|VisualGDB + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Debug|Arduino Genuino Zero (Native USB Port).ActiveCfg = Debug|Arduino Genuino Zero (Native USB Port) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Debug|Arduino Genuino Zero (Native USB Port).Build.0 = Debug|Arduino Genuino Zero (Native USB Port) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Debug|NodeMCU 1 0 (ESP-12E Module).ActiveCfg = Debug|NodeMCU 1 0 (ESP-12E Module) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Debug|NodeMCU 1 0 (ESP-12E Module).Build.0 = Debug|NodeMCU 1 0 (ESP-12E Module) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Debug|VisualGDB.ActiveCfg = Debug|Arduino Genuino Zero (Native USB Port) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Release|Arduino Genuino Zero (Native USB Port).ActiveCfg = Release|Arduino Genuino Zero (Native USB Port) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Release|Arduino Genuino Zero (Native USB Port).Build.0 = Release|Arduino Genuino Zero (Native USB Port) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Release|NodeMCU 1 0 (ESP-12E Module).ActiveCfg = Release|NodeMCU 1 0 (ESP-12E Module) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Release|NodeMCU 1 0 (ESP-12E Module).Build.0 = Release|NodeMCU 1 0 (ESP-12E Module) + {58AFEECD-06E2-4BB7-A13F-E1D5DBAED13F}.Release|VisualGDB.ActiveCfg = Release|Arduino Genuino Zero (Native USB Port) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Debug|Arduino Genuino Zero (Native USB Port).ActiveCfg = Debug|Arduino Genuino Zero (Native USB Port) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Debug|Arduino Genuino Zero (Native USB Port).Build.0 = Debug|Arduino Genuino Zero (Native USB Port) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Debug|NodeMCU 1 0 (ESP-12E Module).ActiveCfg = Debug|NodeMCU 1 0 (ESP-12E Module) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Debug|NodeMCU 1 0 (ESP-12E Module).Build.0 = Debug|NodeMCU 1 0 (ESP-12E Module) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Debug|VisualGDB.ActiveCfg = Debug|Arduino Genuino Zero (Native USB Port) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Release|Arduino Genuino Zero (Native USB Port).ActiveCfg = Release|Arduino Genuino Zero (Native USB Port) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Release|Arduino Genuino Zero (Native USB Port).Build.0 = Release|Arduino Genuino Zero (Native USB Port) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Release|NodeMCU 1 0 (ESP-12E Module).ActiveCfg = Release|NodeMCU 1 0 (ESP-12E Module) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Release|NodeMCU 1 0 (ESP-12E Module).Build.0 = Release|NodeMCU 1 0 (ESP-12E Module) + {6165CD6A-91A4-49FA-977A-48F22086CA8E}.Release|VisualGDB.ActiveCfg = Release|Arduino Genuino Zero (Native USB Port) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {721CAB98-83F8-4035-AC23-77AEA55B634D} + EndGlobalSection +EndGlobal