Compare commits
No commits in common. "pages" and "master" have entirely different histories.
31 changed files with 4707 additions and 5420 deletions
14
.drone.yml
Normal file
14
.drone.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
steps:
|
||||
- name: build
|
||||
image: itsblue.dev/plugins/doxygen
|
||||
settings:
|
||||
doxyfile: docs/Doxyfile-mcss
|
||||
|
||||
- name: publish
|
||||
image: itsblue.dev/plugins/codeberg-pages-deploy
|
||||
settings:
|
||||
folder: docs/html
|
||||
ssh_key:
|
||||
from_secret: gitea-ssh-key
|
21
.gitlab-ci.yml
Normal file
21
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,21 @@
|
|||
# you can delete this line if you're not using Docker
|
||||
# image: busybox:latest
|
||||
|
||||
pages:
|
||||
script:
|
||||
- mkdir -p docs
|
||||
- cd docs
|
||||
# - apt install doxygen texlive-base texlive-latex-extra texlive-fonts-extra texlive-fonts-recommended python3-pip
|
||||
- git clone git://github.com/mosra/m.css
|
||||
# - pip3 install jinja2 Pygments
|
||||
- ./m.css/documentation/doxygen.py ./Doxyfile-mcss
|
||||
- cd ./latex
|
||||
- make
|
||||
- cp refman.pdf ../html/QBluetoothLeUart.pdf
|
||||
- cd ../
|
||||
- mv ./html/ ../public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- master
|
674
LICENSE
Normal file
674
LICENSE
Normal file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
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.
|
||||
|
||||
Qt BluetoothLE UART library
|
||||
Copyright (C) 2021 Itsblue development
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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:
|
||||
|
||||
Qt BluetoothLE UART library Copyright (C) 2021 Itsblue development
|
||||
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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
33
QBluetoothLeUart.pri
Normal file
33
QBluetoothLeUart.pri
Normal file
|
@ -0,0 +1,33 @@
|
|||
!isEmpty(QBLUETOOTHLEUART_LIB):error("QBluetoothLeUart.pri already included")
|
||||
QBLUETOOTHLEUART_LIB = 1
|
||||
|
||||
QBluetoothLeUart_QML {
|
||||
QT += qml quickcontrols2
|
||||
DEFINES += QBluetoothLeUart_QML
|
||||
}
|
||||
|
||||
QT += core bluetooth
|
||||
|
||||
CONFIG += staticlib
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
INCLUDEPATH += $$PWD/
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qbluetoothleuartclient.cpp \
|
||||
$$PWD/qbluetoothleuartdevice.cpp \
|
||||
$$PWD/qbluetoothleuartdevicemodel.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qbluetoothleuartclient.h \
|
||||
$$PWD/qbluetoothleuartdevice.h \
|
||||
$$PWD/qbluetoothleuartdevicemodel.h
|
||||
|
||||
android {
|
||||
QT += androidextras
|
||||
}
|
34
QBluetoothLeUart.pro
Normal file
34
QBluetoothLeUart.pro
Normal file
|
@ -0,0 +1,34 @@
|
|||
!isEmpty(QBLUETOOTHLEUART_LIB):error("QBluetoothLeUart.pri already included")
|
||||
QBLUETOOTHLEUART_LIB = 1
|
||||
|
||||
CONFIG += QBluetoothLeUart_QML
|
||||
|
||||
QBluetoothLeUart_QML {
|
||||
QT += qml quickcontrols2
|
||||
DEFINES += QBluetoothLeUart_QML
|
||||
}
|
||||
|
||||
QT += core bluetooth
|
||||
|
||||
TEMPLATE = lib
|
||||
CONFIG += staticlib
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
qbluetoothleuart.cpp \
|
||||
qbluetoothleuartdevice.cpp
|
||||
|
||||
HEADERS += \
|
||||
qbluetoothleuart.h \
|
||||
qbluetoothleuartdevice.h
|
||||
|
||||
# Default rules for deployment.
|
||||
unix {
|
||||
target.path = $$[QT_INSTALL_PLUGINS]/generic
|
||||
}
|
||||
!isEmpty(target.path): INSTALLS += target
|
355
QBluetoothLeUart.pro.user
Normal file
355
QBluetoothLeUart.pro.user
Normal file
|
@ -0,0 +1,355 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.13.1, 2020-10-08T19:56:41. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{8b2b329f-2b96-47e0-8e3b-213b44b4afec}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
|
||||
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
|
||||
<value type="QString" key="ClangCodeModel.WarningConfigId">Builtin.Questionable</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">4</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.12.6 GCC 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.12.6 GCC 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5126.gcc_64_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="bool">true</value>
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/dorian/Qt/builds/build-QBluetoothLeUart-Desktop_Qt_5_12_6_GCC_64bit-Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/dorian/Qt/builds/build-QBluetoothLeUart-Desktop_Qt_5_12_6_GCC_64bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="int" key="QtQuickCompiler">2</value>
|
||||
<value type="int" key="SeparateDebugInfo">2</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="bool">true</value>
|
||||
<value type="int" key="EnableQmlDebugging">2</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/dorian/Qt/builds/build-QBluetoothLeUart-Desktop_Qt_5_12_6_GCC_64bit-Release</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/dorian/Qt/builds/build-QBluetoothLeUart-Desktop_Qt_5_12_6_GCC_64bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="int" key="QtQuickCompiler">0</value>
|
||||
<value type="int" key="SeparateDebugInfo">2</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="bool">true</value>
|
||||
<value type="int" key="EnableQmlDebugging">0</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/dorian/Qt/builds/build-QBluetoothLeUart-Desktop_Qt_5_12_6_GCC_64bit-Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/dorian/Qt/builds/build-QBluetoothLeUart-Desktop_Qt_5_12_6_GCC_64bit-Profile</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="int" key="QtQuickCompiler">0</value>
|
||||
<value type="int" key="SeparateDebugInfo">0</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
|
||||
<value type="QString">cpu-cycles</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
|
||||
<value type="int" key="Analyzer.Perf.Frequency">250</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
|
||||
<value type="QString">-e</value>
|
||||
<value type="QString">cpu-cycles</value>
|
||||
<value type="QString">--call-graph</value>
|
||||
<value type="QString">dwarf,4096</value>
|
||||
<value type="QString">-F</value>
|
||||
<value type="QString">250</value>
|
||||
</valuelist>
|
||||
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="QString" key="RunConfiguration.Arguments"></value>
|
||||
<value type="bool" key="RunConfiguration.Arguments.multi">false</value>
|
||||
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Qt BluetoothLE UART library
|
||||
|
||||
A library for Qt to make using Bluetooth LE UART easier.
|
||||
Documentation is available [here](https://itsblue-development.itsblue.online/QBluetoothLeUart)
|
117
annotated.html
117
annotated.html
|
@ -1,117 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html" id="m-navbar-current">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>Classes</h1>
|
||||
<ul class="m-doc">
|
||||
<li>class <a href="classQBluetoothLeUartClient.html" class="m-doc">QBluetoothLeUartClient</a> <span class="m-doc">The <a href="classQBluetoothLeUartClient.html" class="m-doc">QBluetoothLeUartClient</a> class can be used to talk to BluetoothLE devices via UART effordlessly. It can be used via C++ and QML.</span></li>
|
||||
<li>class <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> <span class="m-doc">The <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> class is a helper class for use with QBluetoothLeUart. It is used to get device details and connect to devices.</span></li>
|
||||
<li>class <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a> <span class="m-doc">The <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a> class can be used to display available devices in a QML ListView.</span></li>
|
||||
</ul>
|
||||
<script>
|
||||
function toggle(e) {
|
||||
e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
|
||||
'm-doc-expansible' : 'm-doc-collapsible';
|
||||
return false;
|
||||
}
|
||||
/* Collapse all nodes marked as such. Doing it via JS instead of
|
||||
directly in markup so disabling it doesn't harm usability. The list
|
||||
is somehow regenerated on every iteration and shrinks as I change
|
||||
the classes. It's not documented anywhere and I'm not sure if this
|
||||
is the same across browsers, so I am going backwards in that list to
|
||||
be sure. */
|
||||
var collapsed = document.getElementsByClassName("collapsed");
|
||||
for(var i = collapsed.length - 1; i >= 0; --i)
|
||||
collapsed[i].className = 'm-doc-expansible';
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,548 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>QBluetoothLeUartClient class | Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>
|
||||
QBluetoothLeUartClient <span class="m-thin">class</span>
|
||||
</h1>
|
||||
<p>The <a href="classQBluetoothLeUartClient.html" class="m-doc">QBluetoothLeUartClient</a> class can be used to talk to BluetoothLE devices via UART effordlessly. It can be used via C++ and QML.</p>
|
||||
<nav class="m-block m-default">
|
||||
<h3>Contents</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Reference
|
||||
<ul>
|
||||
<li><a href="#pub-types">Public types</a></li>
|
||||
<li><a href="#pub-static-methods">Public static functions</a></li>
|
||||
<li><a href="#pub-methods">Public functions</a></li>
|
||||
<li><a href="#pub-slots">Public slots</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<p>C++ example:</p><pre class="m-code"><span class="cp">#include</span><span class="w"> </span><span class="cpf"><qbluetoothleuartclient.h></span><span class="cp"></span>
|
||||
<span class="k">class</span><span class="w"> </span><span class="nc">MyBluetoothLeClass</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">QObject</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
|
||||
<span class="k">public</span><span class="o">:</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="n">MyBluetoothLeClass</span><span class="p">(</span><span class="n">QObject</span><span class="o">*</span><span class="w"> </span><span class="n">parent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">nullptr</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">QObject</span><span class="p">(</span><span class="n">parent</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">QBluetoothLeUartClient</span><span class="p">();</span><span class="w"></span>
|
||||
|
||||
<span class="w"> </span><span class="n">connect</span><span class="p">(</span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">QBluetoothLeUartClient</span><span class="o">::</span><span class="n">foundNewDevice</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">MyBluetoothLeClass</span><span class="o">::</span><span class="n">handleFoundNewDevice</span><span class="p">);</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="n">connect</span><span class="p">(</span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">QBluetoothLeUartClient</span><span class="o">::</span><span class="n">connectedToDevice</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">MyBluetoothLeClass</span><span class="o">::</span><span class="n">handleBluetoothDeviceConected</span><span class="p">);</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="n">connect</span><span class="p">(</span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">QBluetoothLeUartClient</span><span class="o">::</span><span class="n">dataReceived</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">MyBluetoothLeClass</span><span class="o">::</span><span class="n">handleDataReceived</span><span class="p">);</span><span class="w"></span>
|
||||
|
||||
<span class="w"> </span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="o">-></span><span class="n">startScanningForDevices</span><span class="p">();</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">}</span><span class="w"></span>
|
||||
|
||||
<span class="k">private</span><span class="o">:</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="n">QBluetoothLeUartClient</span><span class="w"> </span><span class="o">*</span><span class="n">ble</span><span class="p">;</span><span class="w"></span>
|
||||
|
||||
<span class="k">private</span><span class="w"> </span><span class="n">slots</span><span class="o">:</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">handleFoundNewDevice</span><span class="p">(</span><span class="n">QBluetoothLeUartDevice</span><span class="o">*</span><span class="w"> </span><span class="n">device</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="n">qDebug</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Found a device: name: "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">device</span><span class="o">-></span><span class="n">getName</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">" address: "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">device</span><span class="o">-></span><span class="n">getAddress</span><span class="p">();</span><span class="w"></span>
|
||||
|
||||
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">device</span><span class="o">-></span><span class="n">getName</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">"My device name"</span><span class="p">){</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="o">-></span><span class="n">stopScanningForDevices</span><span class="p">();</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="o">-></span><span class="n">connectToDevice</span><span class="p">(</span><span class="n">device</span><span class="p">);</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">}</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">}</span><span class="w"></span>
|
||||
|
||||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">handleBluetoothDeviceConected</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="k">this</span><span class="o">-></span><span class="n">ble</span><span class="o">-></span><span class="n">sendData</span><span class="p">(</span><span class="s">"This is my test message"</span><span class="p">);</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">}</span><span class="w"></span>
|
||||
|
||||
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">handleDataReceived</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">QString</span><span class="w"> </span><span class="o">&</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="n">qDebug</span><span class="p">()</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="s">"Data received: "</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="n">s</span><span class="p">;</span><span class="w"></span>
|
||||
<span class="w"> </span><span class="p">}</span><span class="w"></span>
|
||||
<span class="p">};</span><span class="w"></span></pre><p>QML example:</p><pre class="m-code"><span class="kr">import</span> <span class="nx">de</span><span class="p">.</span><span class="nx">itsblue</span><span class="p">.</span><span class="nx">bluetoothleuart</span> <span class="mf">1.0</span>
|
||||
|
||||
<span class="nx">QBluetoothLeUartClient</span> <span class="p">{</span>
|
||||
<span class="kd">id: ble</span>
|
||||
<span class="k">Component.onCompleted:</span> <span class="p">{</span>
|
||||
<span class="nx">ble</span><span class="p">.</span><span class="nx">startScanningForDevices</span><span class="p">()</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">onFoundNewDevice:</span> <span class="p">{</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Found a device: name: "</span> <span class="o">+</span> <span class="nx">device</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s2">" address: "</span> <span class="o">+</span> <span class="nx">device</span><span class="p">.</span><span class="nx">address</span><span class="p">)</span>
|
||||
<span class="k">if</span><span class="p">(</span><span class="nx">device</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="s2">"My device name"</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">ble</span><span class="p">.</span><span class="nx">stopScanningForDevices</span><span class="p">()</span>
|
||||
<span class="nx">ble</span><span class="p">.</span><span class="nx">connectToDevice</span><span class="p">(</span><span class="nx">device</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">onConnectedToDevice:</span> <span class="p">{</span>
|
||||
<span class="nx">ble</span><span class="p">.</span><span class="nx">sendData</span><span class="p">(</span><span class="s2">"This is my test message"</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">onDataReceived:</span> <span class="p">{</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Data received: "</span> <span class="o">+</span> <span class="nx">data</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span></pre><p>To get all available devices in a model, use the <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a>.</p>
|
||||
<section id="pub-types">
|
||||
<h2><a href="#pub-types">Public types</a></h2>
|
||||
<dl class="m-doc">
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">enum <a href="#af6052aceb355d5171ac0d20276211bb7" class="m-doc">BluetoothLeUartClientState</a> { </span><span class="m-doc-wrap"><a href="#af6052aceb355d5171ac0d20276211bb7a16ab5db5dd73533246deb4c3e62a15c0" class="m-doc">Idle</a> = 0,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7a73c62c3a44f56cead1d5d6e73ccd9ef3" class="m-doc">AdapterTurnedOff</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7a70ca0d74d287cb73d0533ebbb19afde7" class="m-doc">LocationPermissionDenied</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7ad909445369e196b44aeb5eb0d4de8829" class="m-doc">Scanning</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7a16f5a126ec8a4f54041b4b425d9ecc57" class="m-doc">ScanFinished</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7af83eacaf7ffa62c7831d7214a0de890a" class="m-doc">Connecting</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7a609ce7ca1a8b38aa184b646632542d52" class="m-doc">ScanningForService</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7adbdbfbfba03d4443c2b3828a7d675803" class="m-doc">ServiceFound</a>,
|
||||
<a href="#af6052aceb355d5171ac0d20276211bb7a1b365b897dc9cbb49d1a31a2cba9f793" class="m-doc">Connected</a> }</span>
|
||||
</dt>
|
||||
<dd>The BluetoothLeUartState enum contains all state of the QBluetoothLeUart class.</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section id="pub-static-methods">
|
||||
<h2><a href="#pub-static-methods">Public static functions</a></h2>
|
||||
<dl class="m-doc">
|
||||
<dt id="a439ffef7bf397f5b502300cfc4c64cc6">
|
||||
<span class="m-doc-wrap-bumper">static void <a href="#a439ffef7bf397f5b502300cfc4c64cc6" class="m-doc-self">init</a>(</span><span class="m-doc-wrap">)</span>
|
||||
</dt>
|
||||
<dd>Function to register QMl types.</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section id="pub-methods">
|
||||
<h2><a href="#pub-methods">Public functions</a></h2>
|
||||
<dl class="m-doc">
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">void <a href="#a518dd07ab439c88f48537474517c0ac5" class="m-doc">setUUIDs</a>(</span><span class="m-doc-wrap">const char uartServiceUUID[36],
|
||||
const char txUUID[36],
|
||||
const char rxUUID[36])</span>
|
||||
</dt>
|
||||
<dd>Function to set the UUIDs of the bluetooth service.</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section id="pub-slots">
|
||||
<h2><a href="#pub-slots">Public slots</a></h2>
|
||||
<dl class="m-doc">
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a80bbbe83418b848e4a7db0cf5ef4f0f7" class="m-doc">startScanningForDevices</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE bool</span>
|
||||
</dt>
|
||||
<dd>Fuction to start scanning for devices.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a6729698429cfc8b77fbe8f82c14f082e" class="m-doc">stopScanningForDevices</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE bool</span>
|
||||
</dt>
|
||||
<dd>Function to stop scanning for devices.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a7280d732e1cb2c857b995f70443a49e9" class="m-doc">getAvailableDevices</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE QList<<a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a>*></span>
|
||||
</dt>
|
||||
<dd>Function to get all devices that were found during the last scan.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a9338b59d55d929683808e5888066b0e6" class="m-doc">getAvailableDevicesDetailList</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE QVariantList</span>
|
||||
</dt>
|
||||
<dd>Function to get a variant list of all devices that were found during the last scan.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#abaa6dedcb1ea7036d077b5d38cfd147e" class="m-doc">getAvailableDevicesModel</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a>*</span>
|
||||
</dt>
|
||||
<dd>Function to get a <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a> with all available devices.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#ac625b96aa0c295387ed813ee146c7110" class="m-doc">getCurrentDevice</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a>*</span>
|
||||
</dt>
|
||||
<dd>Function to get the currently connected device.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a50d74ef6dd2ac09d8e90af28b540abd7" class="m-doc">connectToDevice</a>(</span><span class="m-doc-wrap">int deviceId) -> Q_INVOKABLE bool</span>
|
||||
</dt>
|
||||
<dd>Function connect to a device using its internal id.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#afae86d1aaa2301e1d811e62a75a0af73" class="m-doc">connectToDevice</a>(</span><span class="m-doc-wrap"><a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a>* device) -> Q_INVOKABLE bool</span>
|
||||
</dt>
|
||||
<dd>Function connect to a device using a <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> object.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#ac9985bc027c769d1fc4c9640ba6895fa" class="m-doc">disconnectFromDevice</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE bool</span>
|
||||
</dt>
|
||||
<dd>Function to disconnect from the current device.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#af005db6ad589ef2e99f3a76b02d54836" class="m-doc">sendData</a>(</span><span class="m-doc-wrap">QString data,
|
||||
bool asynchronous = true) -> Q_INVOKABLE bool</span>
|
||||
</dt>
|
||||
<dd>Function to send data to the connected device.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a094551beaf6d56e004bafa17b51b80cd" class="m-doc">getState</a>(</span><span class="m-doc-wrap">) const -> Q_INVOKABLE <a href="classQBluetoothLeUartClient.html#af6052aceb355d5171ac0d20276211bb7" class="m-doc">QBluetoothLeUartClient::<wbr />BluetoothLeUartClientState</a></span>
|
||||
</dt>
|
||||
<dd>Function to get the current state of QBluetoothLeUart.</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Enum documentation</h2>
|
||||
<section class="m-doc-details" id="af6052aceb355d5171ac0d20276211bb7"><div>
|
||||
<h3>
|
||||
enum QBluetoothLeUartClient::<wbr /><a href="#af6052aceb355d5171ac0d20276211bb7" class="m-doc-self">BluetoothLeUartClientState</a>
|
||||
</h3>
|
||||
<p>The BluetoothLeUartState enum contains all state of the QBluetoothLeUart class.</p>
|
||||
<table class="m-table m-fullwidth m-flat m-doc">
|
||||
<thead><tr><th style="width: 1%">Enumerators</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7a16ab5db5dd73533246deb4c3e62a15c0" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7a16ab5db5dd73533246deb4c3e62a15c0">Idle</a></td>
|
||||
<td>
|
||||
<p>Waiting for instrucions</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7a73c62c3a44f56cead1d5d6e73ccd9ef3" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7a73c62c3a44f56cead1d5d6e73ccd9ef3">AdapterTurnedOff</a></td>
|
||||
<td>
|
||||
<p>The bluetooth adapter is turned off</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7a70ca0d74d287cb73d0533ebbb19afde7" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7a70ca0d74d287cb73d0533ebbb19afde7">LocationPermissionDenied</a></td>
|
||||
<td>
|
||||
<p>The location permssion was denied and we are therfor unable to scan!</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7ad909445369e196b44aeb5eb0d4de8829" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7ad909445369e196b44aeb5eb0d4de8829">Scanning</a></td>
|
||||
<td>
|
||||
<p>Scanning for devices</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7a16f5a126ec8a4f54041b4b425d9ecc57" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7a16f5a126ec8a4f54041b4b425d9ecc57">ScanFinished</a></td>
|
||||
<td>
|
||||
<p>Scanning has finished, we are ready to connect</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7af83eacaf7ffa62c7831d7214a0de890a" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7af83eacaf7ffa62c7831d7214a0de890a">Connecting</a></td>
|
||||
<td>
|
||||
<p>Trying to connect</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7a609ce7ca1a8b38aa184b646632542d52" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7a609ce7ca1a8b38aa184b646632542d52">ScanningForService</a></td>
|
||||
<td>
|
||||
<p>Connection was successfull, now scanning for services</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7adbdbfbfba03d4443c2b3828a7d675803" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7adbdbfbfba03d4443c2b3828a7d675803">ServiceFound</a></td>
|
||||
<td>
|
||||
<p>Services were found</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#af6052aceb355d5171ac0d20276211bb7a1b365b897dc9cbb49d1a31a2cba9f793" class="m-doc-self" id="af6052aceb355d5171ac0d20276211bb7a1b365b897dc9cbb49d1a31a2cba9f793">Connected</a></td>
|
||||
<td>
|
||||
<p>Connected. We are now ready to send and receive</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div></section>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Function documentation</h2>
|
||||
<section class="m-doc-details" id="a518dd07ab439c88f48537474517c0ac5"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">void QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a518dd07ab439c88f48537474517c0ac5" class="m-doc-self">setUUIDs</a>(</span><span class="m-doc-wrap">const char uartServiceUUID[36],
|
||||
const char txUUID[36],
|
||||
const char rxUUID[36])</span></span>
|
||||
</h3>
|
||||
<p>Function to set the UUIDs of the bluetooth service.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<thead>
|
||||
<tr><th colspan="2">Parameters</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 1%">uartServiceUUID</td>
|
||||
<td>Service UUID</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>txUUID</td>
|
||||
<td>UUID of the characteristic used to send data</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rxUUID</td>
|
||||
<td>UUID of the characteristic used to receive data</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="a80bbbe83418b848e4a7db0cf5ef4f0f7"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE bool QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a80bbbe83418b848e4a7db0cf5ef4f0f7" class="m-doc-self">startScanningForDevices</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Fuction to start scanning for devices.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>true if the scan started, false if the current state was not Idle</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<p>This function will start the device scanning process and might emit the following signals during scanning:</p><ul><li>foundNewDevice() when a new device is found</li><li>avaliableDevicesChanged() when a new device is found</li><li>scanFinished() when the scan has finished</li><li>scanningErrorOccured() when an error occured</li></ul><aside class="m-note m-default"><h4>See also</h4><p>foundNewDevice()</p><p>avaliableDevicesChanged()</p><p>scanFinished()</p><p>scanningErrorOccured()</p></aside>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="a6729698429cfc8b77fbe8f82c14f082e"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE bool QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a6729698429cfc8b77fbe8f82c14f082e" class="m-doc-self">stopScanningForDevices</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to stop scanning for devices.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>true if the scan was stopped, false if the current state was not Scanning</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="a7280d732e1cb2c857b995f70443a49e9"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE QList<<a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a>*> QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a7280d732e1cb2c857b995f70443a49e9" class="m-doc-self">getAvailableDevices</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to get all devices that were found during the last scan.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>List of all devices found during last scan</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<p>A <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> object can be used to connect to the specific device</p><aside class="m-note m-default"><h4>See also</h4><p><a href="classQBluetoothLeUartClient.html#a50d74ef6dd2ac09d8e90af28b540abd7" class="m-doc">connectToDevice()</a></p></aside>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="a9338b59d55d929683808e5888066b0e6"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE QVariantList QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a9338b59d55d929683808e5888066b0e6" class="m-doc-self">getAvailableDevicesDetailList</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to get a variant list of all devices that were found during the last scan.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>Variant list of all devices found during last scan</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<p>This will return a QVariantList that contains QVariantMaps. The maps contain the following keys:</p><ul><li>"id" (int): the internal id of the device (used to connect to it)</li><li>"name" (QString): the name of the device</li><li>"address" (QString): the bluetooth address of the device</li></ul><aside class="m-note m-default"><h4>See also</h4><p><a href="classQBluetoothLeUartClient.html#a50d74ef6dd2ac09d8e90af28b540abd7" class="m-doc">connectToDevice()</a></p></aside>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="abaa6dedcb1ea7036d077b5d38cfd147e"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a>* QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#abaa6dedcb1ea7036d077b5d38cfd147e" class="m-doc-self">getAvailableDevicesModel</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to get a <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a> with all available devices.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>A <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a> with all available devices</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<aside class="m-note m-default"><h4>See also</h4><p><a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a></p></aside>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="ac625b96aa0c295387ed813ee146c7110"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a>* QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#ac625b96aa0c295387ed813ee146c7110" class="m-doc-self">getCurrentDevice</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to get the currently connected device.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>The currently connected device or nullptr if no device is connected</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="a50d74ef6dd2ac09d8e90af28b540abd7"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE bool QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a50d74ef6dd2ac09d8e90af28b540abd7" class="m-doc-self">connectToDevice</a>(</span><span class="m-doc-wrap">int deviceId) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function connect to a device using its internal id.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<thead>
|
||||
<tr><th colspan="2">Parameters</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 1%">deviceId</td>
|
||||
<td>the internal id of the device</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>false if the device was not found in the internal list of discovered devices, true otherwise</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<p>The id can be found using <a href="classQBluetoothLeUartClient.html#a9338b59d55d929683808e5888066b0e6" class="m-doc">getAvailableDevicesDetailList()</a> The connectedToDevice() signal will be emited as soon as the connection was successfull. As soon as that signal was emited, the <a href="classQBluetoothLeUartClient.html#af005db6ad589ef2e99f3a76b02d54836" class="m-doc">sendData()</a> slot can be used to send data and the dataReceived() signal will be emited whenever data is received.</p><aside class="m-note m-default"><h4>See also</h4><p><a href="classQBluetoothLeUartClient.html#a9338b59d55d929683808e5888066b0e6" class="m-doc">getAvailableDevicesDetailList()</a></p><p>connectedToDevice()</p><p>dataReceived()</p></aside>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="afae86d1aaa2301e1d811e62a75a0af73"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE bool QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#afae86d1aaa2301e1d811e62a75a0af73" class="m-doc-self">connectToDevice</a>(</span><span class="m-doc-wrap"><a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a>* device) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function connect to a device using a <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> object.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<thead>
|
||||
<tr><th colspan="2">Parameters</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 1%">device</td>
|
||||
<td>The device to connect to</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>false if the device was not found in the internal list of discovered devices, true otherwise</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<p>The <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> can be found using <a href="classQBluetoothLeUartClient.html#a7280d732e1cb2c857b995f70443a49e9" class="m-doc">getAvailableDevices()</a> The connectedToDevice() signal will be emited as soon as the connection was successfull. As soon as that signal was emited, the <a href="classQBluetoothLeUartClient.html#af005db6ad589ef2e99f3a76b02d54836" class="m-doc">sendData()</a> slot can be used to send data and the dataReceived() signal will be emited whenever data is received.</p><aside class="m-note m-default"><h4>See also</h4><p><a href="classQBluetoothLeUartClient.html#a7280d732e1cb2c857b995f70443a49e9" class="m-doc">getAvailableDevices()</a></p><p>connectedToDevice()</p><p>dataReceived()</p></aside>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="ac9985bc027c769d1fc4c9640ba6895fa"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE bool QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#ac9985bc027c769d1fc4c9640ba6895fa" class="m-doc-self">disconnectFromDevice</a>(</span><span class="m-doc-wrap">) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to disconnect from the current device.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>false if no device was connected, true otherwise</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="af005db6ad589ef2e99f3a76b02d54836"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE bool QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#af005db6ad589ef2e99f3a76b02d54836" class="m-doc-self">sendData</a>(</span><span class="m-doc-wrap">QString data,
|
||||
bool asynchronous = true) <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to send data to the connected device.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<thead>
|
||||
<tr><th colspan="2">Parameters</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 1%">data</td>
|
||||
<td>The data to send</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>asynchronous</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>Returns</th>
|
||||
<td>false if there was not device connected, true otherwise</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="a094551beaf6d56e004bafa17b51b80cd"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE <a href="classQBluetoothLeUartClient.html#af6052aceb355d5171ac0d20276211bb7" class="m-doc">QBluetoothLeUartClient::<wbr />BluetoothLeUartClientState</a> QBluetoothLeUartClient::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a094551beaf6d56e004bafa17b51b80cd" class="m-doc-self">getState</a>(</span><span class="m-doc-wrap">) const <span class="m-label m-success">public slot</span></span></span>
|
||||
</h3>
|
||||
<p>Function to get the current state of QBluetoothLeUart.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>The current state</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<aside class="m-note m-default"><h4>See also</h4><p>BluetoothLeUartState</p></aside>
|
||||
</div></section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,154 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>QBluetoothLeUartDevice class | Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>
|
||||
QBluetoothLeUartDevice <span class="m-thin">class</span>
|
||||
</h1>
|
||||
<p>The <a href="classQBluetoothLeUartDevice.html" class="m-doc">QBluetoothLeUartDevice</a> class is a helper class for use with QBluetoothLeUart. It is used to get device details and connect to devices.</p>
|
||||
<nav class="m-block m-default">
|
||||
<h3>Contents</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Reference
|
||||
<ul>
|
||||
<li><a href="#pub-methods">Public functions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section id="pub-methods">
|
||||
<h2><a href="#pub-methods">Public functions</a></h2>
|
||||
<dl class="m-doc">
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#a55eb37355852665c1b4557db184c6a89" class="m-doc">getName</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE QString</span>
|
||||
</dt>
|
||||
<dd>Function to get the name of the device.</dd>
|
||||
<dt>
|
||||
<span class="m-doc-wrap-bumper">auto <a href="#aee39a9efbeae1b0b03557b5036d60cc5" class="m-doc">getAddress</a>(</span><span class="m-doc-wrap">) -> Q_INVOKABLE QString</span>
|
||||
</dt>
|
||||
<dd>Function to get the address of the device.</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Function documentation</h2>
|
||||
<section class="m-doc-details" id="a55eb37355852665c1b4557db184c6a89"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE QString QBluetoothLeUartDevice::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a55eb37355852665c1b4557db184c6a89" class="m-doc-self">getName</a>(</span><span class="m-doc-wrap">)</span></span>
|
||||
</h3>
|
||||
<p>Function to get the name of the device.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>The name of the device</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></section>
|
||||
<section class="m-doc-details" id="aee39a9efbeae1b0b03557b5036d60cc5"><div>
|
||||
<h3>
|
||||
<span class="m-doc-wrap-bumper">Q_INVOKABLE QString QBluetoothLeUartDevice::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#aee39a9efbeae1b0b03557b5036d60cc5" class="m-doc-self">getAddress</a>(</span><span class="m-doc-wrap">)</span></span>
|
||||
</h3>
|
||||
<p>Function to get the address of the device.</p>
|
||||
<table class="m-table m-fullwidth m-flat">
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th style="width: 1%">Returns</th>
|
||||
<td>address of the device</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,119 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>QBluetoothLeUartDeviceModel class | Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>
|
||||
QBluetoothLeUartDeviceModel <span class="m-thin">class</span>
|
||||
</h1>
|
||||
<p>The <a href="classQBluetoothLeUartDeviceModel.html" class="m-doc">QBluetoothLeUartDeviceModel</a> class can be used to display available devices in a QML ListView.</p>
|
||||
<p>Example implementation:</p><pre class="m-code"><span class="kr">import</span> <span class="nx">de</span><span class="p">.</span><span class="nx">itsblue</span><span class="p">.</span><span class="nx">bluetoothleuart</span> <span class="mf">1.0</span>
|
||||
|
||||
<span class="nx">QBluetoothLeUartClient</span> <span class="p">{</span>
|
||||
<span class="kd">id: ble</span>
|
||||
<span class="k">Component.onCompleted:</span> <span class="p">{</span>
|
||||
<span class="nx">ble</span><span class="p">.</span><span class="nx">startScanningForDevices</span><span class="p">()</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="nx">ListView</span> <span class="p">{</span>
|
||||
<span class="k">model:</span> <span class="nx">ble</span><span class="p">.</span><span class="nx">availableDevicesModel</span>
|
||||
|
||||
<span class="k">delegate:</span> <span class="nx">ItemDelegate</span> <span class="p">{</span>
|
||||
<span class="k">width:</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">width</span>
|
||||
|
||||
<span class="k">text:</span> <span class="nx">name</span>
|
||||
|
||||
<span class="k">onClicked:</span> <span class="nx">backend</span><span class="p">.</span><span class="nx">bleController</span><span class="p">.</span><span class="nx">connectToDevice</span><span class="p">(</span><span class="nx">device</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
4
docs/.gitignore
vendored
Normal file
4
docs/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/html/
|
||||
/latex/
|
||||
/xml/
|
||||
/m.css/
|
2494
docs/Doxyfile
Normal file
2494
docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
18
docs/Doxyfile-mcss
Normal file
18
docs/Doxyfile-mcss
Normal file
|
@ -0,0 +1,18 @@
|
|||
@INCLUDE = Doxyfile
|
||||
GENERATE_HTML = NO
|
||||
GENERATE_XML = YES
|
||||
XML_PROGRAMLISTING = NO
|
||||
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
|
||||
HTML_EXTRA_STYLESHEET = \
|
||||
https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600 \
|
||||
../css/m-dark+documentation.compiled.css
|
||||
M_THEME_COLOR = #0094ff
|
||||
#M_FAVICON = favicon.png
|
||||
|
||||
# navbar
|
||||
M_LINKS_NAVBAR1 =
|
||||
M_LINKS_NAVBAR2 = "<a href=\"index.html\">Introduction</a>" \
|
||||
annotated \
|
||||
"<a href=\"refman.pdf\">Download</a>"
|
BIN
favicon-dark.png
BIN
favicon-dark.png
Binary file not shown.
Before Width: | Height: | Size: 380 B |
114
files.html
114
files.html
|
@ -1,114 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>Files</h1>
|
||||
<ul class="m-doc">
|
||||
</ul>
|
||||
<script>
|
||||
function toggle(e) {
|
||||
e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
|
||||
'm-doc-expansible' : 'm-doc-collapsible';
|
||||
return false;
|
||||
}
|
||||
/* Collapse all nodes marked as such. Doing it via JS instead of
|
||||
directly in markup so disabling it doesn't harm usability. The list
|
||||
is somehow regenerated on every iteration and shrinks as I change
|
||||
the classes. It's not documented anywhere and I'm not sure if this
|
||||
is the same across browsers, so I am going backwards in that list to
|
||||
be sure. */
|
||||
var collapsed = document.getElementsByClassName("collapsed");
|
||||
for(var i = collapsed.length - 1; i >= 0; --i)
|
||||
collapsed[i].className = 'm-doc-expansible';
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
104
index.html
104
index.html
|
@ -1,104 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>
|
||||
Qt BluetoothLE UART library
|
||||
</h1>
|
||||
<section id="intro_sec"><h2><a href="#intro_sec">Introduction</a></h2><p>This library can be used to talk to BLE devices via UART in Qt. It was designed to make talking to devices like the ESP32 from Qt easier.</p></section><section id="section"><h2><a href="#section">Installation</a></h2><pre class="m-code"><span class="nb">cd</span> yourRepo
|
||||
git submodule add https://itsblue.dev/itsblue-development/QBluetoothLeUart.git
|
||||
git submodule update --init --recursive</pre><p>And in your MyProject.pro include the .pri file:</p><pre class="m-code"><span class="s s-Atom">#</span> <span class="nv">Optional</span><span class="s s-Atom">:</span> <span class="s s-Atom">enable</span> <span class="nv">QML</span> <span class="s s-Atom">stuff</span>
|
||||
<span class="nv">CONFIG</span> <span class="s s-Atom">+=</span> <span class="nv">QBluetoothLeUart_QML</span>
|
||||
<span class="s s-Atom">#</span> <span class="nv">Include</span> <span class="s s-Atom">library</span>
|
||||
<span class="nf">include</span><span class="p">(</span><span class="err">$$</span><span class="nv">PWD</span><span class="o">/</span><span class="nv">QBluetoothLeUart</span><span class="o">/</span><span class="nv">QBluetoothLeUart</span><span class="p">.</span><span class="s s-Atom">pri</span><span class="p">)</span></pre><p>To enable the QML module you need to call <code class="m-code"><span class="n">QBluetoothLeUart</span><span class="o">::</span><span class="n">init</span><span class="p">();</span><span class="w"></span></code> somewhere before app.exec(); in your main.cpp.</p></section><section id="Getting_started"><h2><a href="#Getting_started">Getting_started</a></h2><p>This library currently supports: BluetoothLE UART client</p><section id="BluetoothLE"><h3><a href="#BluetoothLE">UART client</a></h3><p>To get started with the BLE client, see the docs of <a href="classQBluetoothLeUartClient.html" class="m-doc">QBluetoothLeUartClient</a>.</p></section></section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load diff
|
@ -1,99 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>
|
||||
Qt BluetoothLE UART library
|
||||
</h1>
|
||||
<p>A library for Qt to make using Bluetooth LE UART easier. Documentation is available <a href="https://itsblue-development.itsblue.online/QBluetoothLeUart">here</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
114
modules.html
114
modules.html
|
@ -1,114 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>Modules</h1>
|
||||
<ul class="m-doc">
|
||||
</ul>
|
||||
<script>
|
||||
function toggle(e) {
|
||||
e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
|
||||
'm-doc-expansible' : 'm-doc-collapsible';
|
||||
return false;
|
||||
}
|
||||
/* Collapse all nodes marked as such. Doing it via JS instead of
|
||||
directly in markup so disabling it doesn't harm usability. The list
|
||||
is somehow regenerated on every iteration and shrinks as I change
|
||||
the classes. It's not documented anywhere and I'm not sure if this
|
||||
is the same across browsers, so I am going backwards in that list to
|
||||
be sure. */
|
||||
var collapsed = document.getElementsByClassName("collapsed");
|
||||
for(var i = collapsed.length - 1; i >= 0; --i)
|
||||
collapsed[i].className = 'm-doc-expansible';
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
114
namespaces.html
114
namespaces.html
|
@ -1,114 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>Namespaces</h1>
|
||||
<ul class="m-doc">
|
||||
</ul>
|
||||
<script>
|
||||
function toggle(e) {
|
||||
e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
|
||||
'm-doc-expansible' : 'm-doc-collapsible';
|
||||
return false;
|
||||
}
|
||||
/* Collapse all nodes marked as such. Doing it via JS instead of
|
||||
directly in markup so disabling it doesn't harm usability. The list
|
||||
is somehow regenerated on every iteration and shrinks as I change
|
||||
the classes. It's not documented anywhere and I'm not sure if this
|
||||
is the same across browsers, so I am going backwards in that list to
|
||||
be sure. */
|
||||
var collapsed = document.getElementsByClassName("collapsed");
|
||||
for(var i = collapsed.length - 1; i >= 0; --i)
|
||||
collapsed[i].className = 'm-doc-expansible';
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
115
pages.html
115
pages.html
|
@ -1,115 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Qt BluetoothLE UART library</title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600" />
|
||||
<link rel="stylesheet" href="m-dark+documentation.compiled.css" />
|
||||
<link rel="icon" href="favicon-dark.png" type="image/png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#0094ff" />
|
||||
</head>
|
||||
<body>
|
||||
<header><nav id="navigation">
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<a href="index.html" id="m-navbar-brand" class="m-col-t-8 m-col-m-none m-left-m">Qt BluetoothLE UART library</a>
|
||||
<div class="m-col-t-4 m-hide-m m-text-right m-nopadr">
|
||||
<a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<path id="m-doc-search-icon-path" d="m6 0c-3.31 0-6 2.69-6 6 0 3.31 2.69 6 6 6 1.49 0 2.85-0.541 3.89-1.44-0.0164 0.338 0.147 0.759 0.5 1.15l3.22 3.79c0.552 0.614 1.45 0.665 2 0.115 0.55-0.55 0.499-1.45-0.115-2l-3.79-3.22c-0.392-0.353-0.812-0.515-1.15-0.5 0.895-1.05 1.44-2.41 1.44-3.89 0-3.31-2.69-6-6-6zm0 1.56a4.44 4.44 0 0 1 4.44 4.44 4.44 4.44 0 0 1-4.44 4.44 4.44 4.44 0 0 1-4.44-4.44 4.44 4.44 0 0 1 4.44-4.44z"/>
|
||||
</svg></a>
|
||||
<a id="m-navbar-show" href="#navigation" title="Show navigation"></a>
|
||||
<a id="m-navbar-hide" href="#" title="Hide navigation"></a>
|
||||
</div>
|
||||
<div id="m-navbar-collapse" class="m-col-t-12 m-show-m m-col-m-none m-right-m">
|
||||
<div class="m-row">
|
||||
<ol class="m-col-t-6 m-col-m-none">
|
||||
</ol>
|
||||
<ol class="m-col-t-6 m-col-m-none" start="1">
|
||||
<li><a href="index.html">Introduction</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="refman.pdf">Download</a></li>
|
||||
<li class="m-show-m"><a href="#search" class="m-doc-search-icon" title="Search" onclick="return showSearch()"><svg style="height: 0.9rem;" viewBox="0 0 16 16">
|
||||
<use href="#m-doc-search-icon-path" />
|
||||
</svg></a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></header>
|
||||
<main><article>
|
||||
<div class="m-container m-container-inflatable">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<h1>Pages</h1>
|
||||
<ul class="m-doc">
|
||||
<li><a href="md__drone_src_README.html" class="m-doc">Qt BluetoothLE UART library</a> <span class="m-doc"></span></li>
|
||||
</ul>
|
||||
<script>
|
||||
function toggle(e) {
|
||||
e.parentElement.className = e.parentElement.className == 'm-doc-collapsible' ?
|
||||
'm-doc-expansible' : 'm-doc-collapsible';
|
||||
return false;
|
||||
}
|
||||
/* Collapse all nodes marked as such. Doing it via JS instead of
|
||||
directly in markup so disabling it doesn't harm usability. The list
|
||||
is somehow regenerated on every iteration and shrinks as I change
|
||||
the classes. It's not documented anywhere and I'm not sure if this
|
||||
is the same across browsers, so I am going backwards in that list to
|
||||
be sure. */
|
||||
var collapsed = document.getElementsByClassName("collapsed");
|
||||
for(var i = collapsed.length - 1; i >= 0; --i)
|
||||
collapsed[i].className = 'm-doc-expansible';
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></main>
|
||||
<div class="m-doc-search" id="search">
|
||||
<a href="#!" onclick="return hideSearch()"></a>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-m-8 m-push-m-2">
|
||||
<div class="m-doc-search-header m-text m-small">
|
||||
<div><span class="m-label m-default">Tab</span> / <span class="m-label m-default">T</span> to search, <span class="m-label m-default">Esc</span> to close</div>
|
||||
<div id="search-symbolcount">…</div>
|
||||
</div>
|
||||
<div class="m-doc-search-content">
|
||||
<form>
|
||||
<input type="search" name="q" id="search-input" placeholder="Loading …" disabled="disabled" autofocus="autofocus" autocomplete="off" spellcheck="false" />
|
||||
</form>
|
||||
<noscript class="m-text m-danger m-text-center">Unlike everything else in the docs, the search functionality <em>requires</em> JavaScript.</noscript>
|
||||
<div id="search-help" class="m-text m-dim m-text-center">
|
||||
<p class="m-noindent">Search for symbols, directories, files, pages or
|
||||
modules. You can omit any prefix from the symbol or file path; adding a
|
||||
<code>:</code> or <code>/</code> suffix lists all members of given symbol or
|
||||
directory.</p>
|
||||
<p class="m-noindent">Use <span class="m-label m-dim">↓</span>
|
||||
/ <span class="m-label m-dim">↑</span> to navigate through the list,
|
||||
<span class="m-label m-dim">Enter</span> to go.
|
||||
<span class="m-label m-dim">Tab</span> autocompletes common prefix, you can
|
||||
copy a link to the result using <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">L</span> while <span class="m-label m-dim">⌘</span>
|
||||
<span class="m-label m-dim">M</span> produces a Markdown link.</p>
|
||||
</div>
|
||||
<div id="search-notfound" class="m-text m-warning m-text-center">Sorry, nothing was found.</div>
|
||||
<ul id="search-results"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="search-v2.js"></script>
|
||||
<script src="searchdata-v2.js" async="async"></script>
|
||||
<footer><nav>
|
||||
<div class="m-container">
|
||||
<div class="m-row">
|
||||
<div class="m-col-l-10 m-push-l-1">
|
||||
<p>Qt BluetoothLE UART library. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.4 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav></footer>
|
||||
</body>
|
||||
</html>
|
462
qbluetoothleuartclient.cpp
Normal file
462
qbluetoothleuartclient.cpp
Normal file
|
@ -0,0 +1,462 @@
|
|||
#include "qbluetoothleuartclient.h"
|
||||
|
||||
QBluetoothLeUartClient::QBluetoothLeUartClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
currentBluetoothDevice = nullptr;
|
||||
bluetoothController = nullptr;
|
||||
bluetoothService = nullptr;
|
||||
|
||||
state = Idle;
|
||||
|
||||
this->setUUIDs("6e400001-b5a3-f393-e0a9-e50e24dcca9e", "6e400002-b5a3-f393-e0a9-e50e24dcca9e", "6e400003-b5a3-f393-e0a9-e50e24dcca9e");
|
||||
|
||||
// init device discovery agent for scanning
|
||||
this->bluetoothDeviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
|
||||
|
||||
connect(this->bluetoothDeviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &QBluetoothLeUartClient::handleDeviceDiscovered);
|
||||
connect(bluetoothDeviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
|
||||
this, SLOT(handleDeviceScanError(QBluetoothDeviceDiscoveryAgent::Error)));
|
||||
connect(this->bluetoothDeviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &QBluetoothLeUartClient::handleScanFinished);
|
||||
|
||||
// device model for QML
|
||||
this->availableDevicesModel = new QBluetoothLeUartDeviceModel(this->availableDevices, this);
|
||||
}
|
||||
|
||||
QBluetoothLeUartClient::~QBluetoothLeUartClient(){
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// - Slots for QBluetoothLeUart -
|
||||
// ------------------------------
|
||||
|
||||
bool QBluetoothLeUartClient::requestLocationPermission() {
|
||||
|
||||
if(this->isLocationPermissionGranted())
|
||||
return true;
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
// try to get permission
|
||||
QtAndroid::PermissionResultMap resultMap = QtAndroid::requestPermissionsSync({"android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"});
|
||||
bool resultBool = true;
|
||||
for(QtAndroid::PermissionResult result : resultMap) {
|
||||
if(result != QtAndroid::PermissionResult::Granted) {
|
||||
resultBool = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(resultBool) {
|
||||
if(this->state == LocationPermissionDenied)
|
||||
this->setState(Idle);
|
||||
return true;
|
||||
}
|
||||
|
||||
// getting permission the traditional way failed -> open the settings app
|
||||
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); //activity is valid
|
||||
if (activity.isValid())
|
||||
{
|
||||
// get the package name
|
||||
QAndroidJniObject context = QtAndroid::androidContext();
|
||||
QAndroidJniObject applicationPackageName = context.callObjectMethod<jstring>("getPackageName");
|
||||
|
||||
QAndroidJniObject param = QAndroidJniObject::fromString("package:" + applicationPackageName.toString());
|
||||
|
||||
// Equivalent to Jave code: 'Uri uri = Uri::parse("...");'
|
||||
QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", param.object<jstring>());
|
||||
if (!uri.isValid()) {
|
||||
qWarning("ERROR: Unable to create Uri object");
|
||||
return false;
|
||||
}
|
||||
QAndroidJniObject packageName = QAndroidJniObject::fromString("android.settings.APPLICATION_DETAILS_SETTINGS");
|
||||
|
||||
QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V", packageName.object<jstring>());
|
||||
if (!intent.isValid()) {
|
||||
qWarning("ERROR: Unable to create Intent object");
|
||||
return false;
|
||||
}
|
||||
intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("android.intent.category.DEFAULT").object<jstring>());
|
||||
intent.callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object<jobject>());
|
||||
|
||||
activity.callMethod<void>("startActivity","(Landroid/content/Intent;)V",intent.object<jobject>());
|
||||
}
|
||||
else {
|
||||
qWarning() << "ERROR: Activity not valid!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::isLocationPermissionGranted() {
|
||||
#ifdef Q_OS_ANDROID
|
||||
QtAndroid::PermissionResult fineLocationAccess = QtAndroid::checkPermission("android.permission.ACCESS_FINE_LOCATION");
|
||||
QtAndroid::PermissionResult coarseLocationAccess = QtAndroid::checkPermission("android.permission.ACCESS_COARSE_LOCATION");
|
||||
|
||||
return fineLocationAccess == QtAndroid::PermissionResult::Granted && coarseLocationAccess == QtAndroid::PermissionResult::Granted;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::startScanningForDevices(){
|
||||
if(this->state != Idle && this->state != AdapterTurnedOff && this->state != ScanFinished && this->state != LocationPermissionDenied)
|
||||
return false;
|
||||
|
||||
this->availableDevicesModel->clear();
|
||||
|
||||
foreach(QBluetoothLeUartDevice* oldDevice, this->availableDevices)
|
||||
oldDevice->deleteLater();
|
||||
|
||||
this->availableDevices.clear();
|
||||
|
||||
this->setState(Scanning);
|
||||
this->bluetoothDeviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::stopScanningForDevices() {
|
||||
if(this->state != Scanning)
|
||||
return false;
|
||||
|
||||
this->bluetoothDeviceDiscoveryAgent->stop();
|
||||
this->setState(ScanFinished);
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QBluetoothLeUartDevice*> QBluetoothLeUartClient::getAvailableDevices() {
|
||||
return this->availableDevices;
|
||||
}
|
||||
|
||||
QVariantList QBluetoothLeUartClient::getAvailableDevicesDetailList() {
|
||||
|
||||
QVariantList result;
|
||||
|
||||
for(int i=0; i < this->availableDevices.length(); i++) {
|
||||
if(this->availableDevices[i]->getName().isEmpty())
|
||||
continue;
|
||||
|
||||
QVariantMap device;
|
||||
|
||||
device.insert("id", i);
|
||||
device.insert("name", this->availableDevices[i]->getName());
|
||||
device.insert("address", this->availableDevices[i]->getAddress());
|
||||
|
||||
result.append(device);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QBluetoothLeUartDeviceModel* QBluetoothLeUartClient::getAvailableDevicesModel() {
|
||||
return this->availableDevicesModel;
|
||||
}
|
||||
|
||||
QBluetoothLeUartDevice* QBluetoothLeUartClient::getCurrentDevice() {
|
||||
return this->currentBluetoothDevice;
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::connectToDevice(int deviceId) {
|
||||
if(deviceId < 0 || deviceId >= this->availableDevices.length())
|
||||
return false;
|
||||
|
||||
this->connectToDevice(this->availableDevices[deviceId]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::connectToDevice(QBluetoothLeUartDevice *device){
|
||||
if(!this->availableDevices.contains(device))
|
||||
return false;
|
||||
|
||||
if(this->state == Scanning)
|
||||
this->stopScanningForDevices();
|
||||
|
||||
this->currentBluetoothDevice = device;
|
||||
emit this->currentDeviceChanged();
|
||||
|
||||
if (bluetoothController) {
|
||||
bluetoothController->disconnectFromDevice();
|
||||
delete bluetoothController;
|
||||
bluetoothController = 0;
|
||||
}
|
||||
|
||||
// initialize QLowEnergyController
|
||||
bluetoothController = new QLowEnergyController(currentBluetoothDevice->getDevice(), this);
|
||||
bluetoothController->setRemoteAddressType(QLowEnergyController::RandomAddress);
|
||||
|
||||
connect(this->bluetoothController, &QLowEnergyController::serviceDiscovered, this, &QBluetoothLeUartClient::handleServiceDiscovered);
|
||||
connect(this->bluetoothController, &QLowEnergyController::discoveryFinished, this, &QBluetoothLeUartClient::handleServiceScanDone);
|
||||
connect(bluetoothController, SIGNAL(error(QLowEnergyController::Error)),
|
||||
this, SLOT(handleControllerError(QLowEnergyController::Error)));
|
||||
connect(this->bluetoothController, &QLowEnergyController::connected, this, &QBluetoothLeUartClient::handleDeviceConnected);
|
||||
connect(this->bluetoothController, &QLowEnergyController::disconnected, this, &QBluetoothLeUartClient::handleDeviceDisconnected);
|
||||
|
||||
/* Start connecting to device */
|
||||
bluetoothController->connectToDevice();
|
||||
setState(Connecting);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::disconnectFromDevice() {
|
||||
if(this->state < Connecting)
|
||||
return false;
|
||||
|
||||
if(this->state >= Connected)
|
||||
this->bluetoothController->disconnectFromDevice();
|
||||
|
||||
this->bluetoothController->deleteLater();
|
||||
this->bluetoothController = nullptr;
|
||||
|
||||
if(this->bluetoothService != nullptr) {
|
||||
this->bluetoothService->deleteLater();
|
||||
this->bluetoothService = nullptr;
|
||||
}
|
||||
|
||||
this->currentBluetoothDevice->deleteLater();
|
||||
this->currentBluetoothDevice = nullptr;
|
||||
emit this->currentDeviceChanged();
|
||||
|
||||
this->setState(Idle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QBluetoothLeUartClient::sendData(QString data, bool asynchronous){
|
||||
Q_UNUSED(asynchronous)
|
||||
if(this->state != Connected)
|
||||
return false;
|
||||
|
||||
const QLowEnergyCharacteristic RxChar = bluetoothService->characteristic(QBluetoothUuid(QUuid(this->txUUID)));
|
||||
|
||||
bluetoothService->writeCharacteristic(RxChar, data.toUtf8(), QLowEnergyService::WriteWithoutResponse);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
// - Slots for QBluetothDeviceDiscoveryAgent -
|
||||
// -------------------------------------------
|
||||
|
||||
void QBluetoothLeUartClient::handleDeviceDiscovered(const QBluetoothDeviceInfo &device)
|
||||
{
|
||||
// Is it a BLE device?
|
||||
if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
|
||||
//qWarning() << "Discovered BLE Device: name: " << device.name() << " Address: " << device.address().toString() << " UUIDs: " << device.serviceUuids();
|
||||
// ignore all devices that to not support our service
|
||||
if(!device.serviceUuids().contains(QBluetoothUuid(this->uartServiceUUID)))
|
||||
return;
|
||||
|
||||
QBluetoothLeUartDevice *dev = new QBluetoothLeUartDevice(device, this);
|
||||
this->availableDevices.append(dev);
|
||||
this->availableDevicesModel->append(dev);
|
||||
emit this->foundNewDevice(dev);
|
||||
emit this->avaliableDevicesChanged(this->availableDevices);
|
||||
}
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleScanFinished()
|
||||
{
|
||||
if (this->availableDevices.size() == 0)
|
||||
{
|
||||
qWarning() << "No Low Energy devices found";
|
||||
}
|
||||
|
||||
emit this->scanFinished(this->availableDevices);
|
||||
|
||||
setState(ScanFinished);
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleDeviceScanError(QBluetoothDeviceDiscoveryAgent::Error error)
|
||||
{
|
||||
qWarning() << "Scanning ERROR: " << error;
|
||||
|
||||
this->availableDevices.clear();
|
||||
this->availableDevicesModel->clear();
|
||||
|
||||
if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError) {
|
||||
this->setState(AdapterTurnedOff);
|
||||
emit this->scanningErrorOccured(AdapterTurnedOffError);
|
||||
}
|
||||
else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError) {
|
||||
this->setState(AdapterTurnedOff);
|
||||
emit this->scanningErrorOccured(InputOutputError);
|
||||
}
|
||||
else if (error == QBluetoothDeviceDiscoveryAgent::UnknownError) {
|
||||
// check for permission error
|
||||
if(!this->isLocationPermissionGranted()) {
|
||||
this->setState(LocationPermissionDenied);
|
||||
emit this->scanningErrorOccured(LocationPermissionDeniedError);
|
||||
}
|
||||
else
|
||||
emit this->scanningErrorOccured(UnknownError);
|
||||
}
|
||||
else
|
||||
emit this->scanningErrorOccured(UnknownError);
|
||||
|
||||
this->stopScanningForDevices();
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
// - Slots for QLowEnergyController -
|
||||
// ----------------------------------
|
||||
|
||||
void QBluetoothLeUartClient::handleServiceDiscovered(const QBluetoothUuid &uuid){
|
||||
|
||||
//qDebug() << "Found service with ID: " << uuid;
|
||||
|
||||
if(uuid == QBluetoothUuid(QUuid(this->uartServiceUUID))){
|
||||
foundValidUARTService =true;
|
||||
//qDebug() << "UART service found!";
|
||||
}
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleServiceScanDone(){
|
||||
|
||||
delete bluetoothService;
|
||||
bluetoothService=0;
|
||||
|
||||
if(foundValidUARTService){
|
||||
//qDebug() << "Connecting to UART service...";
|
||||
bluetoothService = bluetoothController->createServiceObject(QBluetoothUuid(QUuid(this->uartServiceUUID)),this);
|
||||
}
|
||||
|
||||
if(!bluetoothService){
|
||||
//qDebug() <<"UART service not found";
|
||||
this->disconnectFromDevice();
|
||||
return;
|
||||
}
|
||||
|
||||
/* 3 Step: Service Discovery */
|
||||
connect(this->bluetoothService, &QLowEnergyService::stateChanged, this, &QBluetoothLeUartClient::handleServiceStateChange);
|
||||
connect(this->bluetoothService, &QLowEnergyService::characteristicChanged, this, &QBluetoothLeUartClient::handleServiceCharacteristicChange);
|
||||
connect(this->bluetoothService, &QLowEnergyService::descriptorWritten, this, &QBluetoothLeUartClient::handleServiceDescriptorWritten);
|
||||
|
||||
bluetoothService->discoverDetails();
|
||||
setState(ServiceFound);
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleControllerError(QLowEnergyController::Error error)
|
||||
{
|
||||
qDebug() << "Cannot connect to remote device.";
|
||||
qWarning() << "Controller Error:" << error;
|
||||
this->disconnectFromDevice();
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleDeviceConnected()
|
||||
{
|
||||
//qDebug() << "Device connected";
|
||||
bluetoothController->discoverServices();
|
||||
setState(ScanningForService);
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleDeviceDisconnected()
|
||||
{
|
||||
this->setState(Idle);
|
||||
//qDebug() << "UART service disconnected";
|
||||
qWarning() << "Remote device disconnected";
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// - Slots for QLowEnergyService -
|
||||
// -------------------------------
|
||||
|
||||
void QBluetoothLeUartClient::handleServiceStateChange(QLowEnergyService::ServiceState s)
|
||||
{
|
||||
|
||||
// A descriptoc can only be written if the service is in the ServiceDiscovered state
|
||||
switch (s) {
|
||||
case QLowEnergyService::ServiceDiscovered:
|
||||
{
|
||||
|
||||
//looking for the RX characteristic
|
||||
const QLowEnergyCharacteristic TxChar = bluetoothService->characteristic(QBluetoothUuid(QUuid(this->rxUUID)));
|
||||
if (!TxChar.isValid()){
|
||||
//qDebug() << "Rx characteristic not found";
|
||||
this->disconnectFromDevice();
|
||||
return;
|
||||
}
|
||||
|
||||
//looking for the TX characteristic
|
||||
const QLowEnergyCharacteristic RxChar = bluetoothService->characteristic(QBluetoothUuid(QUuid(this->txUUID)));
|
||||
if (!RxChar.isValid()) {
|
||||
//qDebug() << "Tx characteristic not found";
|
||||
this->disconnectFromDevice();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Bluetooth LE spec Where a characteristic can be notified, a Client Characteristic Configuration descriptor
|
||||
// shall be included in that characteristic as required by the Bluetooth Core Specification
|
||||
// Tx notify is enabled
|
||||
const QLowEnergyDescriptor m_notificationDescTx = TxChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||
|
||||
if (m_notificationDescTx.isValid()) {
|
||||
// enable notification
|
||||
bluetoothService->writeDescriptor(m_notificationDescTx, QByteArray::fromHex("0100"));
|
||||
setState(Connected);
|
||||
emit this->connectedToDevice();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//nothing for now
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleServiceCharacteristicChange(const QLowEnergyCharacteristic &c,const QByteArray &value)
|
||||
{
|
||||
// ignore any other characteristic change
|
||||
if (c.uuid() != QBluetoothUuid(QUuid(this->rxUUID)))
|
||||
return;
|
||||
|
||||
emit dataReceived((QString) value);
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::handleServiceDescriptorWritten(const QLowEnergyDescriptor &d,
|
||||
const QByteArray &value)
|
||||
{
|
||||
if (d.isValid() && d == bluetoothTransmissionDescriptor && value == QByteArray("0000")) {
|
||||
//disabled notifications -> assume disconnect intent
|
||||
this->disconnectFromDevice();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// - Helper functions -
|
||||
// --------------------
|
||||
|
||||
void QBluetoothLeUartClient::init() {
|
||||
#ifdef QBluetoothLeUart_QML
|
||||
qmlRegisterUncreatableType<QBluetoothLeUartDevice>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUartDevice", "QBluetoothLeUartDevice cannot be created");
|
||||
qmlRegisterUncreatableType<QBluetoothLeUartDeviceModel>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUartDeviceModel", "QBluetoothLeUartDeviceModel cannot be created");
|
||||
qmlRegisterType<QBluetoothLeUartClient>("de.itsblue.bluetoothleuart", 1, 0, "QBluetoothLeUart");
|
||||
qRegisterMetaType<QBluetoothLeUartClient::BluetoothLeUartClientState>("QBluetoothLeUart::BluetoothLeUartState");
|
||||
qRegisterMetaType<QBluetoothLeUartClient::BluetoothScanError>("QBluetoothLeUart::BluetoothScanError");
|
||||
#endif
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::setState(QBluetoothLeUartClient::BluetoothLeUartClientState newState)
|
||||
{
|
||||
if (state == newState)
|
||||
return;
|
||||
|
||||
state = newState;
|
||||
emit stateChanged(newState);
|
||||
}
|
||||
|
||||
QBluetoothLeUartClient::BluetoothLeUartClientState QBluetoothLeUartClient::getState() const {
|
||||
return state;
|
||||
}
|
||||
|
||||
void QBluetoothLeUartClient::setUUIDs(const char uartServiceUUID[36], const char txUUID[36], const char rxUUID[36]) {
|
||||
this->uartServiceUUID = uartServiceUUID;
|
||||
this->txUUID = txUUID;
|
||||
this->rxUUID = rxUUID;
|
||||
}
|
367
qbluetoothleuartclient.h
Normal file
367
qbluetoothleuartclient.h
Normal file
|
@ -0,0 +1,367 @@
|
|||
#ifndef BLUETOOTHLEUART_H
|
||||
#define BLUETOOTHLEUART_H
|
||||
|
||||
#include <QBluetoothDeviceDiscoveryAgent>
|
||||
#include <QBluetoothDeviceInfo>
|
||||
#include <QLowEnergyController>
|
||||
#include <QLowEnergyService>
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <QtAndroidExtras>
|
||||
#endif
|
||||
|
||||
#ifdef QBluetoothLeUart_QML
|
||||
#include <QQmlApplicationEngine>
|
||||
#endif
|
||||
|
||||
#include <qbluetoothleuartdevice.h>
|
||||
#include <qbluetoothleuartdevicemodel.h>
|
||||
|
||||
/*!
|
||||
* \mainpage Qt BluetoothLE UART library
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* This library can be used to talk to BLE devices via UART in Qt.
|
||||
* It was designed to make talking to devices like the ESP32 from Qt easier.
|
||||
*
|
||||
* \section section Installation
|
||||
* \code{.sh}
|
||||
* cd yourRepo
|
||||
* git submodule add https://itsblue.dev/itsblue-development/QBluetoothLeUart.git
|
||||
* git submodule update --init --recursive
|
||||
* \endcode
|
||||
*
|
||||
* And in your MyProject.pro include the .pri file:
|
||||
* \code{.pro}
|
||||
* # Optional: enable QML stuff
|
||||
* CONFIG += QBluetoothLeUart_QML
|
||||
* # Include library
|
||||
* include($$PWD/QBluetoothLeUart/QBluetoothLeUart.pri)
|
||||
* \endcode
|
||||
*
|
||||
* To enable the QML module you need to call
|
||||
* \code{.cpp}
|
||||
* QBluetoothLeUart::init();
|
||||
* \endcode
|
||||
* somewhere before app.exec(); in your main.cpp.
|
||||
*
|
||||
* \section Getting_started
|
||||
* This library currently supports: BluetoothLE UART client
|
||||
* \subsection BluetoothLE UART client
|
||||
* To get started with the BLE client, see the docs of QBluetoothLeUartClient.
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief The QBluetoothLeUartClient class can be used to talk to BluetoothLE devices via UART effordlessly.
|
||||
* It can be used via C++ and QML.
|
||||
*
|
||||
* C++ example:
|
||||
* \code{.cpp}
|
||||
* #include <qbluetoothleuartclient.h>
|
||||
* class MyBluetoothLeClass : QObject {
|
||||
* public:
|
||||
* MyBluetoothLeClass(QObject* parent = nullptr) : QObject(parent) {
|
||||
* this->ble = new QBluetoothLeUartClient();
|
||||
*
|
||||
* connect(this->ble, &QBluetoothLeUartClient::foundNewDevice, this, &MyBluetoothLeClass::handleFoundNewDevice);
|
||||
* connect(this->ble, &QBluetoothLeUartClient::connectedToDevice, this, &MyBluetoothLeClass::handleBluetoothDeviceConected);
|
||||
* connect(this->ble, &QBluetoothLeUartClient::dataReceived, this, &MyBluetoothLeClass::handleDataReceived);
|
||||
*
|
||||
* this->ble->startScanningForDevices();
|
||||
* }
|
||||
*
|
||||
* private:
|
||||
* QBluetoothLeUartClient *ble;
|
||||
*
|
||||
* private slots:
|
||||
* void handleFoundNewDevice(QBluetoothLeUartDevice* device) {
|
||||
* qDebug() << "Found a device: name: " << device->getName() << " address: " << device->getAddress();
|
||||
*
|
||||
* if(device->getName() == "My device name"){
|
||||
* this->ble->stopScanningForDevices();
|
||||
* this->ble->connectToDevice(device);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* void handleBluetoothDeviceConected() {
|
||||
* this->ble->sendData("This is my test message");
|
||||
* }
|
||||
*
|
||||
* void handleDataReceived(const QString &s) {
|
||||
* qDebug() << "Data received: " << s;
|
||||
* }
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* QML example:
|
||||
* \code{.qml}
|
||||
* import de.itsblue.bluetoothleuart 1.0
|
||||
*
|
||||
* QBluetoothLeUartClient {
|
||||
* id: ble
|
||||
* Component.onCompleted: {
|
||||
* ble.startScanningForDevices()
|
||||
* }
|
||||
*
|
||||
* onFoundNewDevice: {
|
||||
* console.log("Found a device: name: " + device.name + " address: " + device.address)
|
||||
* if(device.name === "My device name") {
|
||||
* ble.stopScanningForDevices()
|
||||
* ble.connectToDevice(device)
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* onConnectedToDevice: {
|
||||
* ble.sendData("This is my test message")
|
||||
* }
|
||||
*
|
||||
* onDataReceived: {
|
||||
* console.log("Data received: " + data)
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* To get all available devices in a model, use the QBluetoothLeUartDeviceModel.
|
||||
*/
|
||||
class QBluetoothLeUartClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QVariantList availableDevices READ getAvailableDevicesDetailList NOTIFY avaliableDevicesChanged)
|
||||
Q_PROPERTY(QBluetoothLeUartDeviceModel* availableDevicesModel READ getAvailableDevicesModel NOTIFY avaliableDevicesModelChanged)
|
||||
Q_PROPERTY(QBluetoothLeUartDevice* currentDevice READ getCurrentDevice NOTIFY currentDeviceChanged)
|
||||
Q_PROPERTY(BluetoothLeUartClientState state READ getState NOTIFY stateChanged)
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief The BluetoothLeUartState enum contains all state of the QBluetoothLeUart class.
|
||||
*/
|
||||
enum BluetoothLeUartClientState {
|
||||
Idle = 0, /*!< Waiting for instrucions */
|
||||
AdapterTurnedOff, /*!< The bluetooth adapter is turned off */
|
||||
LocationPermissionDenied, /*!< The location permssion was denied and we are therfor unable to scan! */
|
||||
Scanning, /*!< Scanning for devices */
|
||||
ScanFinished, /*!< Scanning has finished, we are ready to connect */
|
||||
Connecting, /*!< Trying to connect */
|
||||
ScanningForService, /*!< Connection was successfull, now scanning for services */
|
||||
ServiceFound, /*!< Services were found */
|
||||
Connected /*!< Connected. We are now ready to send and receive */
|
||||
};
|
||||
Q_ENUM(BluetoothLeUartClientState)
|
||||
|
||||
enum BluetoothScanError {
|
||||
UnknownError,
|
||||
AdapterTurnedOffError,
|
||||
InputOutputError,
|
||||
LocationPermissionDeniedError
|
||||
};
|
||||
Q_ENUM(BluetoothScanError);
|
||||
|
||||
QBluetoothLeUartClient(QObject *parent = nullptr);
|
||||
~QBluetoothLeUartClient();
|
||||
|
||||
/*!
|
||||
* \brief Function to register QMl types
|
||||
*/
|
||||
static void init();
|
||||
|
||||
/*!
|
||||
* \brief Function to set the UUIDs of the bluetooth service
|
||||
* \param uartServiceUUID Service UUID
|
||||
* \param txUUID UUID of the characteristic used to send data
|
||||
* \param rxUUID UUID of the characteristic used to receive data
|
||||
*/
|
||||
void setUUIDs(const char uartServiceUUID[36], const char txUUID[36], const char rxUUID[36]);
|
||||
|
||||
private:
|
||||
|
||||
// The UUIDs
|
||||
QString uartServiceUUID;
|
||||
QString txUUID;
|
||||
QString rxUUID;
|
||||
|
||||
// current state
|
||||
QBluetoothLeUartClient::BluetoothLeUartClientState state;
|
||||
|
||||
// QBluetooth controllers
|
||||
QBluetoothDeviceDiscoveryAgent *bluetoothDeviceDiscoveryAgent;
|
||||
QLowEnergyController *bluetoothController;
|
||||
QLowEnergyService *bluetoothService;
|
||||
|
||||
// Bluetooth device
|
||||
QBluetoothLeUartDevice *currentBluetoothDevice;
|
||||
QList<QBluetoothLeUartDevice*> availableDevices;
|
||||
QLowEnergyDescriptor bluetoothTransmissionDescriptor;
|
||||
bool foundValidUARTService;
|
||||
|
||||
// for QML
|
||||
QBluetoothLeUartDeviceModel* availableDevicesModel;
|
||||
|
||||
public slots:
|
||||
|
||||
Q_INVOKABLE bool requestLocationPermission();
|
||||
|
||||
Q_INVOKABLE bool isLocationPermissionGranted();
|
||||
|
||||
/*!
|
||||
* \brief Fuction to start scanning for devices
|
||||
*
|
||||
* This function will start the device scanning process and might emit
|
||||
* the following signals during scanning:
|
||||
* - foundNewDevice() when a new device is found
|
||||
* - avaliableDevicesChanged() when a new device is found
|
||||
* - scanFinished() when the scan has finished
|
||||
* - scanningErrorOccured() when an error occured
|
||||
*
|
||||
* \see foundNewDevice()
|
||||
* \see avaliableDevicesChanged()
|
||||
* \see scanFinished()
|
||||
* \see scanningErrorOccured()
|
||||
*
|
||||
* \return true if the scan started, false if the current state was not Idle
|
||||
*/
|
||||
Q_INVOKABLE bool startScanningForDevices();
|
||||
|
||||
/*!
|
||||
* \brief Function to stop scanning for devices
|
||||
*
|
||||
* \return true if the scan was stopped, false if the current state was not Scanning
|
||||
*/
|
||||
Q_INVOKABLE bool stopScanningForDevices();
|
||||
|
||||
/*!
|
||||
* \brief Function to get all devices that were found during the last scan
|
||||
*
|
||||
* A QBluetoothLeUartDevice object can be used to connect to the specific device
|
||||
*
|
||||
* \see connectToDevice()
|
||||
*
|
||||
* \return List of all devices found during last scan
|
||||
*/
|
||||
Q_INVOKABLE QList<QBluetoothLeUartDevice*> getAvailableDevices();
|
||||
|
||||
/*!
|
||||
* \brief Function to get a variant list of all devices that were found during the last scan
|
||||
*
|
||||
* This will return a QVariantList that contains QVariantMaps.
|
||||
* The maps contain the following keys:
|
||||
* - "id" (int): the internal id of the device (used to connect to it)
|
||||
* - "name" (QString): the name of the device
|
||||
* - "address" (QString): the bluetooth address of the device
|
||||
*
|
||||
* \see connectToDevice()
|
||||
*
|
||||
* \return Variant list of all devices found during last scan
|
||||
*/
|
||||
Q_INVOKABLE QVariantList getAvailableDevicesDetailList();
|
||||
|
||||
/*!
|
||||
* \brief Function to get a QBluetoothLeUartDeviceModel with all available devices
|
||||
*
|
||||
* \see QBluetoothLeUartDeviceModel
|
||||
*
|
||||
* \return A QBluetoothLeUartDeviceModel with all available devices
|
||||
*/
|
||||
Q_INVOKABLE QBluetoothLeUartDeviceModel* getAvailableDevicesModel();
|
||||
|
||||
/*!
|
||||
* \brief Function to get the currently connected device
|
||||
* \return The currently connected device or nullptr if no device is connected
|
||||
*/
|
||||
Q_INVOKABLE QBluetoothLeUartDevice* getCurrentDevice();
|
||||
|
||||
/*!
|
||||
* \brief Function connect to a device using its internal id
|
||||
*
|
||||
* The id can be found using getAvailableDevicesDetailList()
|
||||
* The connectedToDevice() signal will be emited as soon as the connection was successfull.
|
||||
* As soon as that signal was emited, the sendData() slot can be used to send data and
|
||||
* the dataReceived() signal will be emited whenever data is received.
|
||||
*
|
||||
* \param deviceId the internal id of the device
|
||||
*
|
||||
* \see getAvailableDevicesDetailList()
|
||||
* \see connectedToDevice()
|
||||
* \see dataReceived()
|
||||
*
|
||||
* \return false if the device was not found in the internal list of discovered devices, true otherwise
|
||||
*/
|
||||
Q_INVOKABLE bool connectToDevice(int deviceId);
|
||||
|
||||
/*!
|
||||
* \brief Function connect to a device using a QBluetoothLeUartDevice object
|
||||
*
|
||||
* The QBluetoothLeUartDevice can be found using getAvailableDevices()
|
||||
* The connectedToDevice() signal will be emited as soon as the connection was successfull.
|
||||
* As soon as that signal was emited, the sendData() slot can be used to send data and
|
||||
* the dataReceived() signal will be emited whenever data is received.
|
||||
*
|
||||
* \param device The device to connect to
|
||||
*
|
||||
* \see getAvailableDevices()
|
||||
* \see connectedToDevice()
|
||||
* \see dataReceived()
|
||||
*
|
||||
* \return false if the device was not found in the internal list of discovered devices, true otherwise
|
||||
*/
|
||||
Q_INVOKABLE bool connectToDevice(QBluetoothLeUartDevice *device);
|
||||
|
||||
/*!
|
||||
* \brief Function to disconnect from the current device
|
||||
*
|
||||
* \return false if no device was connected, true otherwise
|
||||
*/
|
||||
Q_INVOKABLE bool disconnectFromDevice();
|
||||
|
||||
/*!
|
||||
* \brief Function to send data to the connected device
|
||||
* \param data The data to send
|
||||
* \return false if there was not device connected, true otherwise
|
||||
*/
|
||||
Q_INVOKABLE bool sendData(QString data, bool asynchronous = true);
|
||||
|
||||
/*!
|
||||
* \brief Function to get the current state of QBluetoothLeUart
|
||||
* \see BluetoothLeUartState
|
||||
* \return The current state
|
||||
*/
|
||||
Q_INVOKABLE QBluetoothLeUartClient::BluetoothLeUartClientState getState() const;
|
||||
|
||||
private slots:
|
||||
void setState(QBluetoothLeUartClient::BluetoothLeUartClientState newState);
|
||||
|
||||
// Slots for QBluetothDeviceDiscoveryAgent
|
||||
void handleDeviceDiscovered(const QBluetoothDeviceInfo&);
|
||||
void handleScanFinished();
|
||||
void handleDeviceScanError(QBluetoothDeviceDiscoveryAgent::Error);
|
||||
|
||||
// Slots for QLowEnergyController
|
||||
void handleServiceDiscovered(const QBluetoothUuid & uuid);
|
||||
void handleServiceScanDone();
|
||||
void handleControllerError(QLowEnergyController::Error);
|
||||
void handleDeviceConnected();
|
||||
void handleDeviceDisconnected();
|
||||
|
||||
// Slots for QLowEnergyService
|
||||
void handleServiceStateChange(QLowEnergyService::ServiceState s);
|
||||
void handleServiceCharacteristicChange(const QLowEnergyCharacteristic &c, const QByteArray &value);
|
||||
void handleServiceDescriptorWritten(const QLowEnergyDescriptor &d, const QByteArray &value);
|
||||
|
||||
signals:
|
||||
void stateChanged(QBluetoothLeUartClient::BluetoothLeUartClientState newState);
|
||||
|
||||
void foundNewDevice(QBluetoothLeUartDevice* device);
|
||||
void avaliableDevicesChanged(QList<QBluetoothLeUartDevice*> avaliableDevices);
|
||||
void avaliableDevicesModelChanged();
|
||||
void currentDeviceChanged();
|
||||
void scanFinished(QList<QBluetoothLeUartDevice*> availableDevices);
|
||||
void scanningErrorOccured(QBluetoothLeUartClient::BluetoothScanError error);
|
||||
|
||||
void connectedToDevice();
|
||||
|
||||
void dataReceived(QString data);
|
||||
|
||||
};
|
||||
|
||||
#endif // BLUETOOTHLEUART_H
|
37
qbluetoothleuartdevice.cpp
Normal file
37
qbluetoothleuartdevice.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "qbluetoothleuartdevice.h"
|
||||
|
||||
QBluetoothLeUartDevice::QBluetoothLeUartDevice(QBluetoothDeviceInfo info, QObject *parent) : QObject(parent)
|
||||
{
|
||||
this->bluetoothDeviceInfo = info;
|
||||
}
|
||||
|
||||
QString QBluetoothLeUartDevice::getName()
|
||||
{
|
||||
if(bluetoothDeviceInfo.isValid())
|
||||
return bluetoothDeviceInfo.name();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
QBluetoothDeviceInfo QBluetoothLeUartDevice::getDevice()
|
||||
{
|
||||
return bluetoothDeviceInfo;
|
||||
}
|
||||
|
||||
QString QBluetoothLeUartDevice::getAddress()
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
// workaround for Core Bluetooth:
|
||||
return bluetoothDeviceInfo.deviceUuid().toString();
|
||||
#else
|
||||
return bluetoothDeviceInfo.address().toString();
|
||||
#endif
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDevice::setDevice(QBluetoothDeviceInfo device)
|
||||
{
|
||||
if(device != this->bluetoothDeviceInfo) {
|
||||
bluetoothDeviceInfo = device;
|
||||
emit deviceChanged();
|
||||
}
|
||||
}
|
48
qbluetoothleuartdevice.h
Normal file
48
qbluetoothleuartdevice.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef DEVICEINFO_H
|
||||
#define DEVICEINFO_H
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <qbluetoothdeviceinfo.h>
|
||||
#include <qbluetoothaddress.h>
|
||||
#include <qbluetoothuuid.h>
|
||||
|
||||
/*!
|
||||
* \brief The QBluetoothLeUartDevice class is a helper class for use with QBluetoothLeUart.
|
||||
* It is used to get device details and connect to devices
|
||||
*/
|
||||
class QBluetoothLeUartDevice: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ getName NOTIFY deviceChanged)
|
||||
Q_PROPERTY(QString address READ getAddress NOTIFY deviceChanged)
|
||||
|
||||
public:
|
||||
QBluetoothLeUartDevice(QBluetoothDeviceInfo device, QObject *parent = nullptr);
|
||||
|
||||
friend class QBluetoothLeUartClient;
|
||||
|
||||
/*!
|
||||
* \brief Function to get the name of the device
|
||||
* \return The name of the device
|
||||
*/
|
||||
Q_INVOKABLE QString getName();
|
||||
|
||||
/*!
|
||||
* \brief Function to get the address of the device
|
||||
* \return address of the device
|
||||
*/
|
||||
Q_INVOKABLE QString getAddress();
|
||||
|
||||
protected:
|
||||
QBluetoothDeviceInfo getDevice();
|
||||
|
||||
private:
|
||||
void setDevice(QBluetoothDeviceInfo device);
|
||||
QBluetoothDeviceInfo bluetoothDeviceInfo;
|
||||
|
||||
signals:
|
||||
void deviceChanged();
|
||||
};
|
||||
|
||||
#endif // DEVICEINFO_H
|
73
qbluetoothleuartdevicemodel.cpp
Normal file
73
qbluetoothleuartdevicemodel.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "qbluetoothleuartdevicemodel.h"
|
||||
|
||||
QBluetoothLeUartDeviceModel::QBluetoothLeUartDeviceModel(QList<QBluetoothLeUartDevice*> availableDevices, QObject* parent) : QAbstractListModel(parent)
|
||||
{
|
||||
this->availableDevices = availableDevices;
|
||||
connect(this, &QBluetoothLeUartDeviceModel::rowsInserted, this, &QBluetoothLeUartDeviceModel::rowCountChanged);
|
||||
connect(this, &QBluetoothLeUartDeviceModel::rowsRemoved, this, &QBluetoothLeUartDeviceModel::rowCountChanged);
|
||||
}
|
||||
|
||||
int QBluetoothLeUartDeviceModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return this->availableDevices.length();
|
||||
}
|
||||
|
||||
QVariant QBluetoothLeUartDeviceModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < rowCount())
|
||||
switch (role) {
|
||||
case NameRole: return this->availableDevices[index.row()]->getName();
|
||||
case IdRole: return index.row();
|
||||
case AddressRole: return this->availableDevices[index.row()]->getAddress();
|
||||
case DeviceRole: return QVariant::fromValue(this->availableDevices[index.row()]);
|
||||
default: return QVariant();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> QBluetoothLeUartDeviceModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{ NameRole, "name" },
|
||||
{ IdRole, "id" },
|
||||
{ AddressRole, "address"},
|
||||
{ DeviceRole, "device" }
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDeviceModel::append(QBluetoothLeUartDevice* device)
|
||||
{
|
||||
foreach(QBluetoothLeUartDevice* existingDevice, this->availableDevices){
|
||||
if(device == existingDevice)
|
||||
// dublicates aren't allowed
|
||||
return;
|
||||
}
|
||||
|
||||
int row = this->availableDevices.length();
|
||||
this->beginInsertRows(QModelIndex(), row, row);
|
||||
this->availableDevices.insert(row, device);
|
||||
this->endInsertRows();
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDeviceModel::remove(int row)
|
||||
{
|
||||
if (row < 0 || row >= this->availableDevices.length())
|
||||
return;
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
this->availableDevices.removeAt(row);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void QBluetoothLeUartDeviceModel::clear() {
|
||||
|
||||
this->beginResetModel();
|
||||
this->resetInternalData();
|
||||
|
||||
this->availableDevices.clear();
|
||||
|
||||
this->endResetModel();
|
||||
|
||||
emit this->rowCountChanged();
|
||||
}
|
69
qbluetoothleuartdevicemodel.h
Normal file
69
qbluetoothleuartdevicemodel.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
#ifndef QBLUETOOTHLEUARTDEVICEMODEL_H
|
||||
#define QBLUETOOTHLEUARTDEVICEMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
#include <qbluetoothleuartdevice.h>
|
||||
|
||||
/*!
|
||||
* \brief The QBluetoothLeUartDeviceModel class can be used to display available devices in a QML ListView.
|
||||
*
|
||||
* Example implementation:
|
||||
* \code{.qml}
|
||||
* import de.itsblue.bluetoothleuart 1.0
|
||||
*
|
||||
* QBluetoothLeUartClient {
|
||||
* id: ble
|
||||
* Component.onCompleted: {
|
||||
* ble.startScanningForDevices()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ListView {
|
||||
* model: ble.availableDevicesModel
|
||||
*
|
||||
* delegate: ItemDelegate {
|
||||
* width: parent.width
|
||||
*
|
||||
* text: name
|
||||
*
|
||||
* onClicked: backend.bleController.connectToDevice(device)
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class QBluetoothLeUartDeviceModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
|
||||
public:
|
||||
friend class QBluetoothLeUartClient;
|
||||
|
||||
enum QBluetoothLeUartDeviceModelRole {
|
||||
NameRole = Qt::DisplayRole,
|
||||
IdRole,
|
||||
AddressRole,
|
||||
DeviceRole
|
||||
};
|
||||
Q_ENUM(QBluetoothLeUartDeviceModelRole)
|
||||
|
||||
int rowCount(const QModelIndex & = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
protected:
|
||||
QBluetoothLeUartDeviceModel(QList<QBluetoothLeUartDevice*> availableDevices, QObject *parent = nullptr);
|
||||
|
||||
void append(QBluetoothLeUartDevice* device);
|
||||
void remove(int row);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QList<QBluetoothLeUartDevice*> availableDevices;
|
||||
|
||||
signals:
|
||||
void rowCountChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // QBLUETOOTHLEUARTDEVICEMODEL_H
|
BIN
refman.pdf
BIN
refman.pdf
Binary file not shown.
897
search-v2.js
897
search-v2.js
|
@ -1,897 +0,0 @@
|
|||
/*
|
||||
This file is part of m.css.
|
||||
|
||||
Copyright © 2017, 2018, 2019, 2020, 2021, 2022
|
||||
Vladimír Vondruš <mosra@centrum.cz>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
"use strict"; /* it summons the Cthulhu in a proper way, they say */
|
||||
|
||||
var Search = {
|
||||
formatVersion: 2, /* the data filename contains this number too */
|
||||
|
||||
dataSize: 0, /* used mainly by tests, not here */
|
||||
symbolCount: '…',
|
||||
trie: null,
|
||||
map: null,
|
||||
mapFlagsOffset: null,
|
||||
typeMap: null,
|
||||
maxResults: 0,
|
||||
|
||||
/* Type sizes and masks. The data is always fetched as 16/32bit number and
|
||||
then masked to 1, 2, 3 or 4 bytes. Fortunately on LE a mask is enough,
|
||||
on BE we'd have to read N bytes before and then mask. */
|
||||
nameSizeBytes: null,
|
||||
nameSizeMask: null,
|
||||
resultIdBytes: null,
|
||||
resultIdMask: null,
|
||||
fileOffsetBytes: null,
|
||||
fileOffsetMask: null,
|
||||
lookaheadBarrierMask: null,
|
||||
|
||||
/* Always contains at least the root node offset and then one node offset
|
||||
per entered character */
|
||||
searchString: '',
|
||||
searchStack: [],
|
||||
|
||||
/* So items don't get selected right away when a cursor is over results but
|
||||
only after mouse moves */
|
||||
mouseMovedSinceLastRender: false,
|
||||
|
||||
/* Whether we can go back in history in order to hide the search box or
|
||||
not. We can't do that if we arrived directly on #search from outside. */
|
||||
canGoBackToHideSearch: false,
|
||||
|
||||
/* Autocompletion in the input field is whitelisted only for character
|
||||
input (so not deletion, cut, or anything else). This is flipped in the
|
||||
onkeypress event and reset after each oninput event. */
|
||||
autocompleteNextInputEvent: false,
|
||||
|
||||
init: function(buffer, maxResults) {
|
||||
let view = new DataView(buffer);
|
||||
|
||||
/* The file is too short to contain at least the headers and empty
|
||||
sections */
|
||||
if(view.byteLength < 31) {
|
||||
console.error("Search data too short");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(view.getUint8(0) != 'M'.charCodeAt(0) ||
|
||||
view.getUint8(1) != 'C'.charCodeAt(0) ||
|
||||
view.getUint8(2) != 'S'.charCodeAt(0)) {
|
||||
console.error("Invalid search data signature");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(view.getUint8(3) != this.formatVersion) {
|
||||
console.error("Invalid search data version");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetch type sizes. The only value that can fail is result ID byte
|
||||
count, where value of 3 has no assigned meaning. */
|
||||
let typeSizes = view.getUint8(4, true);
|
||||
if((typeSizes & 0x01) >> 0 == 0) {
|
||||
this.fileOffsetBytes = 3;
|
||||
this.fileOffsetMask = 0x00ffffff;
|
||||
this.lookaheadBarrierMask = 0x00800000;
|
||||
} else /* (typeSizes & 0x01) >> 0 == 1 */ {
|
||||
this.fileOffsetBytes = 4;
|
||||
this.fileOffsetMask = 0xffffffff;
|
||||
this.lookaheadBarrierMask = 0x80000000;
|
||||
}
|
||||
if((typeSizes & 0x06) >> 1 == 0) {
|
||||
this.resultIdBytes = 2;
|
||||
this.resultIdMask = 0x0000ffff;
|
||||
} else if((typeSizes & 0x06) >> 1 == 1) {
|
||||
this.resultIdBytes = 3;
|
||||
this.resultIdMask = 0x00ffffff;
|
||||
} else if((typeSizes & 0x06) >> 1 == 2) {
|
||||
this.resultIdBytes = 4;
|
||||
this.resultIdMask = 0xffffffff;
|
||||
} else /* (typeSizes & 0x06) >> 1 == 3 */ {
|
||||
console.error("Invalid search data result ID byte value");
|
||||
return false;
|
||||
}
|
||||
if((typeSizes & 0x08) >> 3 == 0) {
|
||||
this.nameSizeBytes = 1;
|
||||
this.nameSizeMask = 0x00ff;
|
||||
} else /* (typeSizes & 0x08) >> 3 == 1 */ {
|
||||
this.nameSizeBytes = 2;
|
||||
this.nameSizeMask = 0xffff;
|
||||
}
|
||||
|
||||
/* Separate the data into the trie and the result / type map. Because
|
||||
we're reading larger values than there might be and then masking out
|
||||
the high bytes, keep extra 1/2 byte padding at the end to avoid
|
||||
OOB errors. */
|
||||
let mapOffset = view.getUint32(12, true);
|
||||
let typeMapOffset = view.getUint32(16, true);
|
||||
/* There may be a 3-byte file offset at the end of the trie which we'll
|
||||
read as 32-bit, add one safety byte in that case */
|
||||
this.trie = new DataView(buffer, 20, mapOffset - 20 + (4 - this.fileOffsetBytes));
|
||||
/* There may be a 3-byte file size (for zero results) which we'll read
|
||||
as 32-bit, add one safety byte in that case */
|
||||
this.map = new DataView(buffer, mapOffset, typeMapOffset - mapOffset + (4 - this.fileOffsetBytes));
|
||||
/* No variable-size types in the type map at the moment */
|
||||
this.typeMap = new DataView(buffer, typeMapOffset);
|
||||
|
||||
/* Offset of the first result map item is after N + 1 offsets and N
|
||||
flags, calculate flag offset from that */
|
||||
this.mapFlagsOffset = this.fileOffsetBytes*(((this.map.getUint32(0, true) & this.fileOffsetMask) - this.fileOffsetBytes)/(this.fileOffsetBytes + 1) + 1);
|
||||
|
||||
/* Set initial properties */
|
||||
this.dataSize = buffer.byteLength;
|
||||
this.symbolCount = view.getUint32(8, true) + " symbols (" + Math.round(this.dataSize/102.4)/10 + " kB)";
|
||||
this.maxResults = maxResults ? maxResults : 100;
|
||||
this.searchString = '';
|
||||
this.searchStack = [this.trie.getUint32(0, true)];
|
||||
|
||||
/* istanbul ignore if */
|
||||
if(typeof document !== 'undefined') {
|
||||
document.getElementById('search-symbolcount').innerHTML = this.symbolCount;
|
||||
document.getElementById('search-input').disabled = false;
|
||||
document.getElementById('search-input').placeholder = "Type something here …";
|
||||
document.getElementById('search-input').focus();
|
||||
|
||||
/* Search for the input value (there might be something already,
|
||||
for example when going back in the browser) */
|
||||
let value = document.getElementById('search-input').value;
|
||||
|
||||
/* Otherwise check the GET parameters for `q` and fill the input
|
||||
with that */
|
||||
if(!value.length) {
|
||||
var args = decodeURIComponent(window.location.search.substr(1)).trim().split('&');
|
||||
for(var i = 0; i != args.length; ++i) {
|
||||
if(args[i].substring(0, 2) != 'q=') continue;
|
||||
|
||||
value = document.getElementById('search-input').value = args[i].substring(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(value.length) Search.searchAndRender(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
download: /* istanbul ignore next */ function(url) {
|
||||
var req = window.XDomainRequest ? new XDomainRequest() : new XMLHttpRequest();
|
||||
if(!req) return;
|
||||
|
||||
req.open("GET", url, true);
|
||||
req.responseType = 'arraybuffer';
|
||||
req.onreadystatechange = function() {
|
||||
if(req.readyState != 4) return;
|
||||
|
||||
Search.init(req.response);
|
||||
}
|
||||
req.send();
|
||||
},
|
||||
|
||||
base85decode: function(base85string) {
|
||||
function charValue(char) {
|
||||
if(char >= 48 && char < 58) /* 0-9 -> 0-9 */
|
||||
return char - 48 + 0;
|
||||
if(char >= 65 && char < 91) /* A-Z -> 10-35 */
|
||||
return char - 65 + 10;
|
||||
if(char >= 97 && char < 123) /* a-z -> 36-61 */
|
||||
return char - 97 + 36;
|
||||
if(char == 33) /* ! -> 62 */
|
||||
return 62;
|
||||
/* skipping 34 (') */
|
||||
if(char >= 35 && char < 39) /* #-& -> 63-66 */
|
||||
return char - 35 + 63;
|
||||
/* skipping 39 (") */
|
||||
if(char >= 40 && char < 44) /* (-+ -> 67-70 */
|
||||
return char - 40 + 67;
|
||||
/* skipping 44 (,) */
|
||||
if(char == 45) /* - -> 71 */
|
||||
return 71;
|
||||
if(char >= 59 && char < 65) /* ;-@ -> 72-77 */
|
||||
return char - 59 + 72;
|
||||
if(char >= 94 && char < 97) /* ^-` -> 78-80 */
|
||||
return char - 94 + 78;
|
||||
if(char >= 123 && char < 127) /* {-~ -> 81-84 */
|
||||
return char - 123 + 81;
|
||||
|
||||
return 0; /* Interpret padding values as zeros */
|
||||
}
|
||||
|
||||
/* Pad the string for easier decode later. We don't read past the file
|
||||
end, so it doesn't matter what garbage is there. */
|
||||
if(base85string.length % 5) {
|
||||
console.log("Expected properly padded base85 data");
|
||||
return;
|
||||
}
|
||||
|
||||
let buffer = new ArrayBuffer(base85string.length*4/5);
|
||||
let data8 = new DataView(buffer);
|
||||
for(let i = 0; i < base85string.length; i += 5) {
|
||||
let char1 = charValue(base85string.charCodeAt(i + 0));
|
||||
let char2 = charValue(base85string.charCodeAt(i + 1));
|
||||
let char3 = charValue(base85string.charCodeAt(i + 2));
|
||||
let char4 = charValue(base85string.charCodeAt(i + 3));
|
||||
let char5 = charValue(base85string.charCodeAt(i + 4));
|
||||
|
||||
data8.setUint32(i*4/5, char5 +
|
||||
char4*85 +
|
||||
char3*85*85 +
|
||||
char2*85*85*85 +
|
||||
char1*85*85*85*85, false); /* BE, yes */
|
||||
}
|
||||
|
||||
return buffer;
|
||||
},
|
||||
|
||||
load: function(base85string) {
|
||||
return this.init(this.base85decode(base85string));
|
||||
},
|
||||
|
||||
/* http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html */
|
||||
toUtf8: function(string) { return unescape(encodeURIComponent(string)); },
|
||||
fromUtf8: function(string) { return decodeURIComponent(escape(string)); },
|
||||
|
||||
autocompletedCharsToUtf8: function(chars) {
|
||||
/* Strip incomplete UTF-8 chars from the autocompletion end */
|
||||
for(let i = chars.length - 1; i >= 0; --i) {
|
||||
let c = chars[i];
|
||||
|
||||
/* We're safe, finish */
|
||||
if(
|
||||
/* ASCII value at the end */
|
||||
(c < 128 && i + 1 == chars.length) ||
|
||||
|
||||
/* Full two-byte character at the end */
|
||||
((c & 0xe0) == 0xc0 && i + 2 == chars.length) ||
|
||||
|
||||
/* Full three-byte character at the end */
|
||||
((c & 0xf0) == 0xe0 && i + 3 == chars.length) ||
|
||||
|
||||
/* Full four-byte character at the end */
|
||||
((c & 0xf8) == 0xf0 && i + 4 == chars.length)
|
||||
) break;
|
||||
|
||||
/* Continuing UTF-8 character, go further back */
|
||||
if((c & 0xc0) == 0x80) continue;
|
||||
|
||||
/* Otherwise the character is not complete, drop it from the end */
|
||||
chars.length = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Convert the autocompleted UTF-8 sequence to a string */
|
||||
let suggestedTabAutocompletionString = '';
|
||||
for(let i = 0; i != chars.length; ++i)
|
||||
suggestedTabAutocompletionString += String.fromCharCode(chars[i]);
|
||||
return suggestedTabAutocompletionString;
|
||||
},
|
||||
|
||||
/* Returns the values in UTF-8, but input is in whatever shitty 16bit
|
||||
encoding JS has */
|
||||
search: function(searchString) {
|
||||
/* Normalize the search string first, convert to UTF-8 and trim spaces
|
||||
from the left. From the right they're trimmed only if nothing is
|
||||
found, see below. */
|
||||
searchString = this.toUtf8(searchString.toLowerCase().replace(/^\s+/,''));
|
||||
|
||||
/* TODO: maybe i could make use of InputEvent.data and others here */
|
||||
|
||||
/* Find longest common prefix of previous and current value so we don't
|
||||
need to needlessly search again */
|
||||
let max = Math.min(searchString.length, this.searchString.length);
|
||||
let commonPrefix = 0;
|
||||
for(; commonPrefix != max; ++commonPrefix)
|
||||
if(searchString[commonPrefix] != this.searchString[commonPrefix]) break;
|
||||
|
||||
/* Drop items off the stack if it has has more than is needed for the
|
||||
common prefix (it needs to have at least one item, though) */
|
||||
if(commonPrefix + 1 < this.searchStack.length)
|
||||
this.searchStack.splice(commonPrefix + 1, this.searchStack.length - commonPrefix - 1);
|
||||
|
||||
/* Add new characters from the search string */
|
||||
let foundPrefix = commonPrefix;
|
||||
for(; foundPrefix != searchString.length; ++foundPrefix) {
|
||||
/* Calculate offset and count of children */
|
||||
let offset = this.searchStack[this.searchStack.length - 1];
|
||||
|
||||
/* If there's a lot of results, the result count is a 16bit BE value
|
||||
instead */
|
||||
let resultCount = this.trie.getUint8(offset);
|
||||
let resultCountSize = 1;
|
||||
if(resultCount & 0x80) {
|
||||
resultCount = this.trie.getUint16(offset, false) & ~0x8000;
|
||||
++resultCountSize;
|
||||
}
|
||||
|
||||
let childCount = this.trie.getUint8(offset + resultCountSize);
|
||||
|
||||
/* Go through all children and find the next offset */
|
||||
let childOffset = offset + resultCountSize + 1 + resultCount*this.resultIdBytes;
|
||||
let found = false;
|
||||
for(let j = 0; j != childCount; ++j) {
|
||||
if(String.fromCharCode(this.trie.getUint8(childOffset + j)) != searchString[foundPrefix])
|
||||
continue;
|
||||
|
||||
this.searchStack.push(this.trie.getUint32(childOffset + childCount + j*this.fileOffsetBytes, true) & this.fileOffsetMask & ~this.lookaheadBarrierMask);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Character not found */
|
||||
if(!found) {
|
||||
/* If we found everything except spaces at the end, pretend the
|
||||
spaces aren't there. On the other hand, we *do* want to
|
||||
try searching with the spaces first -- it can narrow down
|
||||
the result list for page names or show subpages (which are
|
||||
after a lookahead barrier that's a space). */
|
||||
if(!searchString.substr(foundPrefix).trim().length)
|
||||
searchString = searchString.substr(0, foundPrefix);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the whole found prefix for next time */
|
||||
this.searchString = searchString.substr(0, foundPrefix);
|
||||
|
||||
/* If the whole thing was not found, return an empty result and offer
|
||||
external search */
|
||||
if(foundPrefix != searchString.length) {
|
||||
/* istanbul ignore if */
|
||||
if(typeof document !== 'undefined') {
|
||||
let link = document.getElementById('search-external');
|
||||
if(link)
|
||||
link.href = link.dataset.searchEngine.replace('{query}', encodeURIComponent(searchString));
|
||||
}
|
||||
return [[], ''];
|
||||
}
|
||||
|
||||
/* Otherwise gather the results */
|
||||
let suggestedTabAutocompletionChars = [];
|
||||
let results = [];
|
||||
let leaves = [[this.searchStack[this.searchStack.length - 1], 0]];
|
||||
while(leaves.length) {
|
||||
/* Pop offset from the queue */
|
||||
let current = leaves.shift();
|
||||
let offset = current[0];
|
||||
let suffixLength = current[1];
|
||||
|
||||
/* Calculate child count. If there's a lot of results, the count
|
||||
"leaks over" to the child count storage. */
|
||||
/* TODO: hmmm. this is helluvalot duplicated code. hmm. */
|
||||
let resultCount = this.trie.getUint8(offset);
|
||||
let resultCountSize = 1;
|
||||
if(resultCount & 0x80) {
|
||||
resultCount = this.trie.getUint16(offset, false) & ~0x8000;
|
||||
++resultCountSize;
|
||||
}
|
||||
|
||||
let childCount = this.trie.getUint8(offset + resultCountSize);
|
||||
|
||||
/* Populate the results with all values associated with this node */
|
||||
for(let i = 0; i != resultCount; ++i) {
|
||||
let index = this.trie.getUint32(offset + resultCountSize + 1 + i*this.resultIdBytes, true) & this.resultIdMask;
|
||||
results.push(this.gatherResult(index, suffixLength, 0xffffff)); /* should be enough haha */
|
||||
|
||||
/* 'nuff said. */
|
||||
if(results.length >= this.maxResults)
|
||||
return [results, this.autocompletedCharsToUtf8(suggestedTabAutocompletionChars)];
|
||||
}
|
||||
|
||||
/* Dig deeper */
|
||||
let childOffset = offset + resultCountSize + 1 + resultCount*this.resultIdBytes;
|
||||
for(let j = 0; j != childCount; ++j) {
|
||||
let offsetBarrier = this.trie.getUint32(childOffset + childCount + j*this.fileOffsetBytes, true) & this.fileOffsetMask;
|
||||
|
||||
/* Lookahead barrier, don't dig deeper */
|
||||
if(offsetBarrier & this.lookaheadBarrierMask) continue;
|
||||
|
||||
/* Append to the queue */
|
||||
leaves.push([offsetBarrier & ~this.lookaheadBarrierMask, suffixLength + 1]);
|
||||
|
||||
/* We don't have anything yet and this is the only path
|
||||
forward, add the char to suggested Tab autocompletion. Can't
|
||||
extract it from the leftmost 8 bits of offsetBarrier because
|
||||
that would make it negative, have to load as Uint8 instead.
|
||||
Also can't use String.fromCharCode(), because later doing
|
||||
str.charCodeAt() would give me back UTF-16 values, which is
|
||||
absolutely unwanted when all I want is check for truncated
|
||||
UTF-8. */
|
||||
if(!results.length && leaves.length == 1 && childCount == 1)
|
||||
suggestedTabAutocompletionChars.push(this.trie.getUint8(childOffset + j));
|
||||
}
|
||||
}
|
||||
|
||||
return [results, this.autocompletedCharsToUtf8(suggestedTabAutocompletionChars)];
|
||||
},
|
||||
|
||||
gatherResult: function(index, suffixLength, maxUrlPrefix) {
|
||||
let flags = this.map.getUint8(this.mapFlagsOffset + index);
|
||||
let resultOffset = this.map.getUint32(index*this.fileOffsetBytes, true) & this.fileOffsetMask;
|
||||
|
||||
/* The result is an alias, parse the aliased prefix */
|
||||
let aliasedIndex = null;
|
||||
if((flags & 0xf0) == 0x00) {
|
||||
aliasedIndex = this.map.getUint32(resultOffset, true) & this.resultIdMask;
|
||||
resultOffset += this.resultIdBytes;
|
||||
}
|
||||
|
||||
/* The result has a prefix, parse that first, recursively */
|
||||
let name = '';
|
||||
let url = '';
|
||||
if(flags & (1 << 3)) {
|
||||
let prefixIndex = this.map.getUint32(resultOffset, true) & this.resultIdMask;
|
||||
let prefixUrlPrefixLength = Math.min(this.map.getUint16(resultOffset + this.resultIdBytes, true) & this.nameSizeMask, maxUrlPrefix);
|
||||
|
||||
let prefix = this.gatherResult(prefixIndex, 0 /*ignored*/, prefixUrlPrefixLength);
|
||||
name = prefix.name;
|
||||
url = prefix.url;
|
||||
|
||||
resultOffset += this.resultIdBytes + this.nameSizeBytes;
|
||||
}
|
||||
|
||||
/* The result has a suffix, extract its length */
|
||||
let resultSuffixLength = 0;
|
||||
if(flags & (1 << 0)) {
|
||||
resultSuffixLength = this.map.getUint16(resultOffset, true) & this.nameSizeMask;
|
||||
resultOffset += this.nameSizeBytes;
|
||||
}
|
||||
|
||||
let nextResultOffset = this.map.getUint32((index + 1)*this.fileOffsetBytes, true) & this.fileOffsetMask;
|
||||
|
||||
/* Extract name */
|
||||
let j = resultOffset;
|
||||
for(; j != nextResultOffset; ++j) {
|
||||
let c = this.map.getUint8(j);
|
||||
|
||||
/* End of null-delimited name */
|
||||
if(!c) {
|
||||
++j;
|
||||
break; /* null-delimited */
|
||||
}
|
||||
|
||||
name += String.fromCharCode(c); /* eheh. IS THIS FAST?! */
|
||||
}
|
||||
|
||||
/* The result is an alias and we're not deep inside resolving a prefix,
|
||||
extract the aliased name and URL */
|
||||
/* TODO: this abuses 0xffffff to guess how the call stack is deep and
|
||||
that's just wrong, fix! */
|
||||
if(aliasedIndex != null && maxUrlPrefix == 0xffffff) {
|
||||
let alias = this.gatherResult(aliasedIndex, 0 /* ignored */, 0xffffff); /* should be enough haha */
|
||||
|
||||
/* Keeping in UTF-8, as we need that for proper slicing (and concatenating) */
|
||||
return {name: name,
|
||||
alias: alias.name,
|
||||
url: alias.url,
|
||||
flags: alias.flags,
|
||||
cssClass: alias.cssClass,
|
||||
typeName: alias.typeName,
|
||||
suffixLength: suffixLength + resultSuffixLength};
|
||||
}
|
||||
|
||||
/* Otherwise extract URL from here */
|
||||
let max = Math.min(j + maxUrlPrefix - url.length, nextResultOffset);
|
||||
for(; j != max; ++j) {
|
||||
url += String.fromCharCode(this.map.getUint8(j));
|
||||
}
|
||||
|
||||
/* This is an alias, return what we have, without parsed CSS class and
|
||||
type name as those are retrieved from the final target type */
|
||||
if(!(flags >> 4))
|
||||
return {name: name,
|
||||
url: url,
|
||||
flags: flags & 0x0f,
|
||||
suffixLength: suffixLength + resultSuffixLength};
|
||||
|
||||
/* Otherwise, get CSS class and type name for the result label */
|
||||
let typeMapIndex = (flags >> 4) - 1;
|
||||
let cssClass = [
|
||||
/* Keep in sync with _search.py */
|
||||
'm-default',
|
||||
'm-primary',
|
||||
'm-success',
|
||||
'm-warning',
|
||||
'm-danger',
|
||||
'm-info',
|
||||
'm-dim'
|
||||
][this.typeMap.getUint8(typeMapIndex*2)];
|
||||
let typeNameOffset = this.typeMap.getUint8(typeMapIndex*2 + 1);
|
||||
let nextTypeNameOffset = this.typeMap.getUint8((typeMapIndex + 1)*2 + 1);
|
||||
let typeName = '';
|
||||
for(let j = typeNameOffset; j != nextTypeNameOffset; ++j)
|
||||
typeName += String.fromCharCode(this.typeMap.getUint8(j));
|
||||
|
||||
/* Keeping in UTF-8, as we need that for proper slicing (and
|
||||
concatenating). Strip the type from the flags, as it's now expressed
|
||||
directly. */
|
||||
return {name: name,
|
||||
url: url,
|
||||
flags: flags & 0x0f,
|
||||
cssClass: cssClass,
|
||||
typeName: typeName,
|
||||
suffixLength: suffixLength + resultSuffixLength};
|
||||
},
|
||||
|
||||
escape: function(name) {
|
||||
return name.replace(/[\"&<>]/g, function (a) {
|
||||
return { '"': '"', '&': '&', '<': '<', '>': '>' }[a];
|
||||
});
|
||||
},
|
||||
escapeForRtl: function(name) {
|
||||
/* Besides the obvious escaping of HTML entities we also need
|
||||
to escape punctuation, because due to the RTL hack to cut
|
||||
text off on left side the punctuation characters get
|
||||
reordered (of course). Prepending ‎ works for most
|
||||
characters, parentheses we need to *soak* in it. But only
|
||||
the right ones. And that for some reason needs to be also for &.
|
||||
Huh. https://en.wikipedia.org/wiki/Right-to-left_mark */
|
||||
return this.escape(name).replace(/[:=]/g, '‎$&').replace(/(\)|>|&|\/)/g, '‎$&‎');
|
||||
},
|
||||
|
||||
renderResults: /* istanbul ignore next */ function(resultsSuggestedTabAutocompletion) {
|
||||
if(!this.searchString.length) {
|
||||
document.getElementById('search-help').style.display = 'block';
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
document.getElementById('search-notfound').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('search-help').style.display = 'none';
|
||||
|
||||
/* Results found */
|
||||
if(resultsSuggestedTabAutocompletion[0].length) {
|
||||
let results = resultsSuggestedTabAutocompletion[0];
|
||||
|
||||
document.getElementById('search-results').style.display = 'block';
|
||||
document.getElementById('search-notfound').style.display = 'none';
|
||||
|
||||
let list = '';
|
||||
for(let i = 0; i != results.length; ++i) {
|
||||
/* Labels + */
|
||||
list += '<li' + (i ? '' : ' id="search-current"') + '><a href="' + results[i].url + '" onmouseover="selectResult(event)" data-md-link-title="' + this.escape(results[i].name.substr(results[i].name.length - this.searchString.length - results[i].suffixLength)) + '"><div class="m-label m-flat ' + results[i].cssClass + '">' + results[i].typeName + '</div>' + (results[i].flags & 2 ? '<div class="m-label m-danger">deprecated</div>' : '') + (results[i].flags & 4 ? '<div class="m-label m-danger">deleted</div>' : '');
|
||||
|
||||
/* Render the alias (cut off from the right) */
|
||||
if(results[i].alias) {
|
||||
list += '<div class="m-doc-search-alias"><span class="m-text m-dim">' + this.escape(results[i].name.substr(0, results[i].name.length - this.searchString.length - results[i].suffixLength)) + '</span><span class="m-doc-search-typed">' + this.escape(results[i].name.substr(results[i].name.length - this.searchString.length - results[i].suffixLength, this.searchString.length)) + '</span>' + this.escapeForRtl(results[i].name.substr(results[i].name.length - results[i].suffixLength)) + '<span class="m-text m-dim">: ' + this.escape(results[i].alias) + '</span>';
|
||||
|
||||
/* Render the normal thing (cut off from the left, have to
|
||||
escape for RTL) */
|
||||
} else {
|
||||
list += '<div><span class="m-text m-dim">' + this.escapeForRtl(results[i].name.substr(0, results[i].name.length - this.searchString.length - results[i].suffixLength)) + '</span><span class="m-doc-search-typed">' + this.escapeForRtl(results[i].name.substr(results[i].name.length - this.searchString.length - results[i].suffixLength, this.searchString.length)) + '</span>' + this.escapeForRtl(results[i].name.substr(results[i].name.length - results[i].suffixLength));
|
||||
}
|
||||
|
||||
/* The closing */
|
||||
list += '</div></a></li>';
|
||||
}
|
||||
document.getElementById('search-results').innerHTML = this.fromUtf8(list);
|
||||
document.getElementById('search-current').scrollIntoView(true);
|
||||
|
||||
/* Append the suggested tab autocompletion, if any, and if the user
|
||||
didn't just delete it */
|
||||
let searchInput = document.getElementById('search-input');
|
||||
if(this.autocompleteNextInputEvent && resultsSuggestedTabAutocompletion[1].length && searchInput.selectionEnd == searchInput.value.length) {
|
||||
let suggestedTabAutocompletion = this.fromUtf8(resultsSuggestedTabAutocompletion[1]);
|
||||
|
||||
let lengthBefore = searchInput.value.length;
|
||||
searchInput.value += suggestedTabAutocompletion;
|
||||
searchInput.setSelectionRange(lengthBefore, searchInput.value.length);
|
||||
}
|
||||
|
||||
/* Nothing found */
|
||||
} else {
|
||||
document.getElementById('search-results').innerHTML = '';
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
document.getElementById('search-notfound').style.display = 'block';
|
||||
}
|
||||
|
||||
/* Don't allow things to be selected just by motionless mouse cursor
|
||||
suddenly appearing over a search result */
|
||||
this.mouseMovedSinceLastRender = false;
|
||||
|
||||
/* Reset autocompletion, if it was allowed. It'll get whitelisted next
|
||||
time a character gets inserted. */
|
||||
this.autocompleteNextInputEvent = false;
|
||||
},
|
||||
|
||||
searchAndRender: /* istanbul ignore next */ function(value) {
|
||||
let prev = performance.now();
|
||||
let results = this.search(value);
|
||||
let after = performance.now();
|
||||
this.renderResults(results);
|
||||
if(this.searchString.length) {
|
||||
document.getElementById('search-symbolcount').innerHTML =
|
||||
results[0].length + (results[0].length >= this.maxResults ? '+' : '') + " results (" + Math.round((after - prev)*10)/10 + " ms)";
|
||||
} else
|
||||
document.getElementById('search-symbolcount').innerHTML = this.symbolCount;
|
||||
},
|
||||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
function selectResult(event) {
|
||||
if(!Search.mouseMovedSinceLastRender) return;
|
||||
|
||||
if(event.currentTarget.parentNode.id == 'search-current') return;
|
||||
|
||||
let current = document.getElementById('search-current');
|
||||
current.removeAttribute('id');
|
||||
event.currentTarget.parentNode.id = 'search-current';
|
||||
}
|
||||
|
||||
/* This is separated from showSearch() because we need non-destructive behavior
|
||||
when appearing directly on a URL with #search */ /* istanbul ignore next */
|
||||
function updateForSearchVisible() {
|
||||
/* Prevent accidental scrolling of the body, prevent page layout jumps */
|
||||
let scrolledBodyWidth = document.body.offsetWidth;
|
||||
document.body.style.overflow = 'hidden';
|
||||
document.body.style.paddingRight = (document.body.offsetWidth - scrolledBodyWidth) + 'px';
|
||||
|
||||
document.getElementById('search-input').value = '';
|
||||
document.getElementById('search-input').focus();
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
document.getElementById('search-notfound').style.display = 'none';
|
||||
document.getElementById('search-help').style.display = 'block';
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
function showSearch() {
|
||||
window.location.hash = '#search';
|
||||
Search.canGoBackToHideSearch = true;
|
||||
|
||||
updateForSearchVisible();
|
||||
document.getElementById('search-symbolcount').innerHTML = Search.symbolCount;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
function hideSearch() {
|
||||
/* If the search box was opened using showSearch(), we can go back in the
|
||||
history. Otherwise (for example when we landed to #search from a
|
||||
bookmark or another server), going back would not do the right thing and
|
||||
in that case we simply replace the current history state. */
|
||||
if(Search.canGoBackToHideSearch) {
|
||||
Search.canGoBackToHideSearch = false;
|
||||
window.history.back();
|
||||
} else {
|
||||
window.location.hash = '#!';
|
||||
window.history.replaceState('', '', window.location.pathname);
|
||||
}
|
||||
|
||||
/* Restore scrollbar, prevent page layout jumps */
|
||||
document.body.style.overflow = 'auto';
|
||||
document.body.style.paddingRight = '0';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
function copyToKeyboard(text) {
|
||||
/* Append to the popup, appending to document.body would cause it to
|
||||
scroll when focused */
|
||||
let searchPopup = document.getElementsByClassName('m-doc-search')[0];
|
||||
let textarea = document.createElement("textarea");
|
||||
textarea.value = text;
|
||||
searchPopup.appendChild(textarea);
|
||||
textarea.focus();
|
||||
textarea.select();
|
||||
|
||||
document.execCommand('copy');
|
||||
|
||||
searchPopup.removeChild(textarea);
|
||||
document.getElementById('search-input').focus();
|
||||
}
|
||||
|
||||
/* Only in case we're running in a browser. Why a simple if(document) doesn't
|
||||
work is beyond me. */ /* istanbul ignore if */
|
||||
if(typeof document !== 'undefined') {
|
||||
document.getElementById('search-input').oninput = function(event) {
|
||||
Search.searchAndRender(document.getElementById('search-input').value);
|
||||
};
|
||||
|
||||
document.onkeydown = function(event) {
|
||||
/* Search shown */
|
||||
if(window.location.hash == '#search') {
|
||||
/* Close the search */
|
||||
if(event.key == 'Escape') {
|
||||
hideSearch();
|
||||
|
||||
/* Focus the search input, if not already, using T or Tab */
|
||||
} else if((!document.activeElement || document.activeElement.id != 'search-input') && (event.key.toLowerCase() == 't' || event.key == 'Tab') && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
||||
document.getElementById('search-input').focus();
|
||||
return false; /* so T doesn't get entered into the box */
|
||||
|
||||
/* Fill in the autocompleted selection */
|
||||
} else if(event.key == 'Tab' && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
||||
/* But only if the input has selection at the end */
|
||||
let input = document.getElementById('search-input');
|
||||
if(input.selectionEnd == input.value.length && input.selectionStart != input.selectionEnd) {
|
||||
input.setSelectionRange(input.value.length, input.value.length);
|
||||
return false; /* so input won't lose focus */
|
||||
}
|
||||
|
||||
/* Select next item */
|
||||
} else if(event.key == 'ArrowDown') {
|
||||
let current = document.getElementById('search-current');
|
||||
if(current) {
|
||||
let next = current.nextSibling;
|
||||
if(next) {
|
||||
current.id = '';
|
||||
next.id = 'search-current';
|
||||
next.scrollIntoView(false);
|
||||
}
|
||||
}
|
||||
return false; /* so the keypress doesn't affect input cursor */
|
||||
|
||||
/* Select prev item */
|
||||
} else if(event.key == 'ArrowUp') {
|
||||
let current = document.getElementById('search-current');
|
||||
if(current) {
|
||||
let prev = current.previousSibling;
|
||||
if(prev) {
|
||||
current.id = '';
|
||||
prev.id = 'search-current';
|
||||
prev.scrollIntoView(false);
|
||||
}
|
||||
}
|
||||
return false; /* so the keypress doesn't affect input cursor */
|
||||
|
||||
/* Go to result (if any) */
|
||||
} else if(event.key == 'Enter') {
|
||||
let result = document.getElementById('search-current');
|
||||
if(result) {
|
||||
result.firstElementChild.click();
|
||||
|
||||
/* We might be staying on the same page, so restore scrollbar,
|
||||
and prevent page layout jumps */
|
||||
document.body.style.overflow = 'auto';
|
||||
document.body.style.paddingRight = '0';
|
||||
}
|
||||
return false; /* so the form doesn't get sent */
|
||||
|
||||
/* Copy (Markdown) link to keyboard */
|
||||
} else if((event.key.toLowerCase() == 'l' || event.key.toLowerCase() == 'm') && event.metaKey) {
|
||||
let result = document.getElementById('search-current');
|
||||
if(result) {
|
||||
let plain = event.key.toLowerCase() == 'l';
|
||||
let link = plain ? result.firstElementChild.href :
|
||||
'[' + result.firstElementChild.dataset.mdLinkTitle + '](' + result.firstElementChild.href + ')';
|
||||
|
||||
copyToKeyboard(link);
|
||||
|
||||
/* Add CSS class to the element for visual feedback (this
|
||||
will get removed on keyup), but only if it's not already
|
||||
there (in case of key repeat, e.g.) */
|
||||
if(result.className.indexOf('m-doc-search-copied') == -1)
|
||||
result.className += ' m-doc-search-copied';
|
||||
console.log("Copied " + (plain ? "link" : "Markdown link") + " to " + result.firstElementChild.dataset.mdLinkTitle);
|
||||
}
|
||||
|
||||
return false; /* so L doesn't get entered into the box */
|
||||
|
||||
/* Looks like the user is inserting some text (and not cutting,
|
||||
copying or whatever), allow autocompletion for the new
|
||||
character. The oninput event resets this back to false, so this
|
||||
basically whitelists only keyboard input, including Shift-key
|
||||
and special chars using right Alt (or equivalent on Mac), but
|
||||
excluding Ctrl-key, which is usually not for text input. In the
|
||||
worst case the autocompletion won't be allowed ever, which is
|
||||
much more acceptable behavior than having no ability to disable
|
||||
it and annoying the users. */
|
||||
} else if(event.key != 'Backspace' && event.key != 'Delete' && !event.metaKey && (!event.ctrlKey || event.altKey)
|
||||
/* Don't ever attempt autocompletion with Android virtual
|
||||
keyboards, as those report all `event.key`s as
|
||||
`Unidentified` (on Chrome) or `Process` (on Firefox) with
|
||||
`event.code` 229 and thus we have no way to tell if a text
|
||||
is entered or deleted. See this WONTFIX bug for details:
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=118639
|
||||
Couldn't find any similar bugreport for Firefox, but I
|
||||
assume the virtual keyboard is to blame.
|
||||
|
||||
An alternative is to hook into inputEvent, which has the
|
||||
data, but ... there's more cursed issues right after that:
|
||||
|
||||
- setSelectionRange() in Chrome on Android only renders
|
||||
stuff, but doesn't actually act as such. Pressing
|
||||
Backspace will only remove the highlight, but the text
|
||||
stays here. Only delay-calling it through a timeout will
|
||||
work as intended. Possibly related SO suggestion (back
|
||||
then not even the rendering worked properly):
|
||||
https://stackoverflow.com/a/13235951
|
||||
Possibly related Chrome bug:
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=32865
|
||||
|
||||
- On Firefox Mobile, programmatically changing an input
|
||||
value (for the autocompletion highlight) will trigger an
|
||||
input event, leading to search *and* autocompletion being
|
||||
triggered again. Ultimately that results in newly typed
|
||||
characters not replacing the autocompletion but rather
|
||||
inserting before it, corrupting the searched string. This
|
||||
event has to be explicitly ignored.
|
||||
|
||||
- On Firefox Mobile, deleting a highlight with the
|
||||
backspace key will result in *three* input events instead
|
||||
of one:
|
||||
1. `deleteContentBackward` removing the selection (same
|
||||
as Chrome or desktop Firefox)
|
||||
2. `deleteContentBackward` removing *the whole word*
|
||||
that contained the selection (or the whole text if
|
||||
it's just one word)
|
||||
3. `insertCompositionText`, adding the word back in,
|
||||
resulting in the same state as (1).
|
||||
I have no idea WHY it has to do this (possibly some
|
||||
REALLY NASTY workaround to trigger correct font shaping?)
|
||||
but ultimately it results in the autocompletion being
|
||||
added again right after it got deleted, making this whole
|
||||
thing VERY annoying to use.
|
||||
|
||||
I attempted to work around the above, but it resulted in a
|
||||
huge amount of browser-specific code that achieves only 90%
|
||||
of the goal, with certain corner cases still being rather
|
||||
broken (such as autocompletion randomly triggering when
|
||||
erasing the text, even though it shouldn't). So disabling
|
||||
autocompletion on this HELLISH BROKEN PLATFORM is the best
|
||||
option at the moment. */
|
||||
&& event.key != 'Unidentified' && event.key != 'Process'
|
||||
) {
|
||||
Search.autocompleteNextInputEvent = true;
|
||||
/* Otherwise reset the flag, because when the user would press e.g.
|
||||
the 'a' key and then e.g. ArrowRight (which doesn't trigger
|
||||
oninput), a Backspace after would still result in
|
||||
autocompleteNextInputEvent, because nothing reset it back. */
|
||||
} else {
|
||||
Search.autocompleteNextInputEvent = false;
|
||||
}
|
||||
|
||||
/* Search hidden */
|
||||
} else {
|
||||
/* Open the search on the T or Tab key */
|
||||
if((event.key.toLowerCase() == 't' || event.key == 'Tab') && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
||||
showSearch();
|
||||
return false; /* so T doesn't get entered into the box */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.onkeyup = function(event) {
|
||||
/* Remove highlight after key is released after a link copy */
|
||||
if((event.key.toLowerCase() == 'l' || event.key.toLowerCase() == 'm') && event.metaKey) {
|
||||
let result = document.getElementById('search-current');
|
||||
if(result) result.className = result.className.replace(' m-doc-search-copied', '');
|
||||
}
|
||||
};
|
||||
|
||||
/* Allow selecting items by mouse hover only after it moves once the
|
||||
results are populated. This prevents a random item getting selected if
|
||||
the cursor is left motionless over the result area. */
|
||||
document.getElementById('search-results').onmousemove = function() {
|
||||
Search.mouseMovedSinceLastRender = true;
|
||||
};
|
||||
|
||||
/* If #search is already present in the URL, hide the scrollbar etc. for a
|
||||
consistent experience */
|
||||
if(window.location.hash == '#search') updateForSearchVisible();
|
||||
}
|
||||
|
||||
/* For Node.js testing */ /* istanbul ignore else */
|
||||
if(typeof module !== 'undefined') { module.exports = { Search: Search }; }
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue