commit
2ab1a0cbeb
115 changed files with 5835 additions and 779 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
*.iml
|
||||
wear/wear.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
661
LICENSE.txt
Normal file
661
LICENSE.txt
Normal file
|
@ -0,0 +1,661 @@
|
|||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 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 Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are 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.
|
||||
|
||||
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.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
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 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 work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero 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 Affero 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 Affero 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 Affero 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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero 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 your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
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 AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
|
@ -57,48 +57,42 @@ android {
|
|||
}
|
||||
}
|
||||
productFlavors {
|
||||
flavorDimensions "standard", "wear"
|
||||
flavorDimensions "standard", "limits", "wear"
|
||||
adult {
|
||||
dimension "limits"
|
||||
buildConfigField "int", "MAXBOLUS", "17"
|
||||
}
|
||||
teenage {
|
||||
dimension "limits"
|
||||
buildConfigField "int", "MAXBOLUS", "10"
|
||||
}
|
||||
child {
|
||||
dimension "limits"
|
||||
buildConfigField "int", "MAXBOLUS", "5"
|
||||
}
|
||||
full {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||
buildConfigField "int", "MAXBOLUS", "17"
|
||||
}
|
||||
fullteenage {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||
buildConfigField "int", "MAXBOLUS", "10"
|
||||
}
|
||||
fullchild {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||
buildConfigField "int", "MAXBOLUS", "5"
|
||||
}
|
||||
danarcontrol {
|
||||
pumpcontrol {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "false"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "int", "MAXBOLUS", "17"
|
||||
}
|
||||
careportal {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "false"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "false"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "int", "MAXBOLUS", "17"
|
||||
}
|
||||
openloop {
|
||||
dimension "standard"
|
||||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "int", "MAXBOLUS", "17"
|
||||
}
|
||||
wear {
|
||||
dimension "wear"
|
||||
|
@ -126,7 +120,9 @@ dependencies {
|
|||
compile 'com.squareup:otto:1.3.7'
|
||||
compile 'com.j256.ormlite:ormlite-core:4.46'
|
||||
compile 'com.j256.ormlite:ormlite-android:4.46'
|
||||
compile 'com.github.tony19:logback-android-classic:1.1.1-4'
|
||||
compile('com.github.tony19:logback-android-classic:1.1.1-6') {
|
||||
exclude group: 'com.google.android', module: 'android'
|
||||
}
|
||||
compile 'org.slf4j:slf4j-api:1.7.12'
|
||||
compile 'com.jjoe64:graphview:4.0.1'
|
||||
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar'
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
<activity android:name=".PreferencesActivity" />
|
||||
<activity android:name=".AgreementActivity" />
|
||||
<activity android:name=".plugins.DanaR.History.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.DanaRKorean.History.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
|
||||
|
@ -80,6 +81,10 @@
|
|||
android:name=".plugins.DanaR.Services.ExecutionService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".plugins.DanaRKorean.Services.ExecutionService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<service android:name=".plugins.Wear.wearintegration.WatchUpdaterService" android:exported="true" >
|
||||
<intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter>
|
||||
|
|
|
@ -15,7 +15,7 @@ public class Config {
|
|||
public static final boolean SMSCOMMUNICATORENABLED = true;
|
||||
|
||||
public static final boolean DANAR = true && BuildConfig.PUMPDRIVERS;
|
||||
public static final boolean MM640G = false && BuildConfig.PUMPDRIVERS;
|
||||
public static final boolean DANARKOREAN = true && BuildConfig.PUMPDRIVERS;
|
||||
|
||||
public static final boolean detailedLog = true;
|
||||
public static final boolean logFunctionCalls = true;
|
||||
|
|
|
@ -39,8 +39,6 @@ import info.nightscout.utils.LocaleHelper;
|
|||
public class MainActivity extends AppCompatActivity {
|
||||
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
|
||||
|
||||
private static KeepAliveReceiver keepAliveReceiver;
|
||||
|
||||
static final int CASE_STORAGE = 0x1;
|
||||
static final int CASE_SMS = 0x2;
|
||||
|
||||
|
@ -77,11 +75,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
// no action
|
||||
}
|
||||
|
||||
if (keepAliveReceiver == null) {
|
||||
keepAliveReceiver = new KeepAliveReceiver();
|
||||
startService(new Intent(this, ExecutionService.class));
|
||||
keepAliveReceiver.setAlarm(this);
|
||||
}
|
||||
|
||||
setUpTabs(false);
|
||||
}
|
||||
|
||||
|
@ -90,6 +84,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
String lang = SP.getString("language", "en");
|
||||
LocaleHelper.setLocale(getApplicationContext(), lang);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
recreate();
|
||||
try { // activity may be destroyed
|
||||
setUpTabs(ev.isSwitchToLast());
|
||||
|
@ -97,6 +94,8 @@ public class MainActivity extends AppCompatActivity {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setUpTabs(boolean switchToLast) {
|
||||
TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this);
|
||||
|
@ -164,8 +163,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
// break;
|
||||
case R.id.nav_exit:
|
||||
log.debug("Exiting");
|
||||
keepAliveReceiver.cancelAlarm(this);
|
||||
|
||||
MainApp.instance().stopKeepAliveService();
|
||||
MainApp.bus().post(new EventAppExit());
|
||||
MainApp.closeDbHelper();
|
||||
finish();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
|
@ -22,9 +23,10 @@ import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPe
|
|||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanFragment;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopFragment;
|
||||
import info.nightscout.androidaps.plugins.MM640g.MM640gFragment;
|
||||
import info.nightscout.androidaps.plugins.NSProfileViewer.NSProfileViewerFragment;
|
||||
import info.nightscout.androidaps.plugins.MDI.MDIFragment;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment;
|
||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
|
||||
|
@ -37,11 +39,13 @@ import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment;
|
|||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
|
||||
import info.nightscout.androidaps.plugins.Wear.WearFragment;
|
||||
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
|
||||
public class MainApp extends Application {
|
||||
private static Logger log = LoggerFactory.getLogger(MainApp.class);
|
||||
private static KeepAliveReceiver keepAliveReceiver;
|
||||
|
||||
private static Bus sBus;
|
||||
private static MainApp sInstance;
|
||||
|
@ -70,12 +74,13 @@ public class MainApp extends Application {
|
|||
pluginsList.add(OverviewFragment.getPlugin());
|
||||
pluginsList.add(ActionsFragment.getPlugin());
|
||||
if (Config.DANAR) pluginsList.add(DanaRFragment.getPlugin());
|
||||
if (Config.MM640G) pluginsList.add(MM640gFragment.getPlugin());
|
||||
if (Config.DANARKOREAN) pluginsList.add(DanaRKoreanFragment.getPlugin());
|
||||
if (Config.CAREPORTALENABLED) pluginsList.add(CareportalFragment.getPlugin());
|
||||
pluginsList.add(MDIFragment.getPlugin());
|
||||
pluginsList.add(VirtualPumpFragment.getPlugin());
|
||||
if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin());
|
||||
if (Config.OPENAPSMAENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
|
||||
pluginsList.add(NSProfileViewerFragment.getPlugin());
|
||||
pluginsList.add(NSProfileFragment.getPlugin());
|
||||
pluginsList.add(SimpleProfileFragment.getPlugin());
|
||||
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
|
||||
pluginsList.add(TreatmentsFragment.getPlugin());
|
||||
|
@ -94,6 +99,26 @@ public class MainApp extends Application {
|
|||
MainApp.getConfigBuilder().initialize();
|
||||
}
|
||||
MainApp.getConfigBuilder().uploadAppStart();
|
||||
|
||||
startKeepAliveService();
|
||||
}
|
||||
|
||||
private void startKeepAliveService() {
|
||||
if (keepAliveReceiver == null) {
|
||||
keepAliveReceiver = new KeepAliveReceiver();
|
||||
if (Config.DANAR) {
|
||||
startService(new Intent(this, info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService.class));
|
||||
startService(new Intent(this, info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService.class));
|
||||
}
|
||||
keepAliveReceiver.setAlarm(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void stopKeepAliveService(){
|
||||
if(keepAliveReceiver!=null)
|
||||
keepAliveReceiver.cancelAlarm(this);
|
||||
}
|
||||
|
||||
public static Bus bus() {
|
||||
|
|
|
@ -17,6 +17,7 @@ import info.nightscout.androidaps.interfaces.PluginBase;
|
|||
import info.nightscout.androidaps.plugins.DanaR.BluetoothDevicePreference;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.utils.LocaleHelper;
|
||||
|
||||
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
@ -89,13 +90,12 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
addPreferencesFromResource(R.xml.pref_nightscout);
|
||||
if (Config.DANAR) {
|
||||
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
|
||||
if (danaRPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
if (danaRPlugin.isEnabled(PluginBase.PUMP) || danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
addPreferencesFromResource(R.xml.pref_danar);
|
||||
addPreferencesFromResource(R.xml.pref_danarprofile);
|
||||
}
|
||||
}
|
||||
if (Config.MM640G)
|
||||
addPreferencesFromResource(R.xml.pref_mm640g);
|
||||
if (Config.SMSCOMMUNICATORENABLED)
|
||||
addPreferencesFromResource(R.xml.pref_smscommunicator);
|
||||
addPreferencesFromResource(R.xml.pref_others);
|
||||
|
|
|
@ -22,9 +22,6 @@ import org.slf4j.LoggerFactory;
|
|||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
|
@ -36,10 +33,11 @@ import info.nightscout.androidaps.db.Treatment;
|
|||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.NSProfileViewer.NSProfileViewerPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||
|
@ -76,7 +74,7 @@ public class DataService extends IntentService {
|
|||
nsClientEnabled = true;
|
||||
}
|
||||
|
||||
boolean isNSProfile = ConfigBuilderPlugin.getActiveProfile().getClass().equals(NSProfileViewerPlugin.class);
|
||||
boolean isNSProfile = ConfigBuilderPlugin.getActiveProfile().getClass().equals(NSProfilePlugin.class);
|
||||
|
||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
boolean nsUploadOnly = SP.getBoolean("ns_upload_only", false);
|
||||
|
@ -95,12 +93,11 @@ public class DataService extends IntentService {
|
|||
// Objectives 0
|
||||
ObjectivesPlugin.bgIsAvailableInNS = true;
|
||||
ObjectivesPlugin.saveProgress();
|
||||
} else if (isNSProfile && Intents.ACTION_NEW_PROFILE.equals(action)){
|
||||
// always handle Profili if NSProfile is enabled without looking at nsUploadOnly
|
||||
} else if (isNSProfile && Intents.ACTION_NEW_PROFILE.equals(action)) {
|
||||
// always handle Profile if NSProfile is enabled without looking at nsUploadOnly
|
||||
handleNewDataFromNSClient(intent);
|
||||
} else if (!nsUploadOnly &&
|
||||
(Intents.ACTION_NEW_PROFILE.equals(action) ||
|
||||
Intents.ACTION_NEW_TREATMENT.equals(action) ||
|
||||
(Intents.ACTION_NEW_TREATMENT.equals(action) ||
|
||||
Intents.ACTION_CHANGED_TREATMENT.equals(action) ||
|
||||
Intents.ACTION_REMOVED_TREATMENT.equals(action) ||
|
||||
Intents.ACTION_NEW_STATUS.equals(action) ||
|
||||
|
@ -152,7 +149,7 @@ public class DataService extends IntentService {
|
|||
BgReading bgReading = new BgReading();
|
||||
|
||||
bgReading.value = bundle.getDouble(Intents.EXTRA_BG_ESTIMATE);
|
||||
bgReading.slope = bundle.getDouble(Intents.EXTRA_BG_SLOPE);
|
||||
bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME);
|
||||
bgReading.battery_level = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY);
|
||||
bgReading.timeIndex = bundle.getLong(Intents.EXTRA_TIMESTAMP);
|
||||
bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW);
|
||||
|
@ -248,21 +245,24 @@ public class DataService extends IntentService {
|
|||
String activeProfile = bundles.getString("activeprofile");
|
||||
String profile = bundles.getString("profile");
|
||||
NSProfile nsProfile = new NSProfile(new JSONObject(profile), activeProfile);
|
||||
if (MainApp.getConfigBuilder() == null) {
|
||||
log.error("Config builder not ready on receive profile");
|
||||
return;
|
||||
}
|
||||
MainApp.bus().post(new EventNewBasalProfile(nsProfile));
|
||||
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
if (pump != null) {
|
||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
if (SP.getBoolean("syncprofiletopump", false))
|
||||
pump.setNewBasalProfile(nsProfile);
|
||||
if (SP.getBoolean("syncprofiletopump", false)) {
|
||||
if (pump.setNewBasalProfile(nsProfile) == PumpInterface.SUCCESS) {
|
||||
SmsCommunicatorPlugin smsCommunicatorPlugin = (SmsCommunicatorPlugin) MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class);
|
||||
if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) {
|
||||
smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.error("No active pump selected");
|
||||
}
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Received profile: " + activeProfile + " " + profile);
|
||||
MainApp.bus().post(new EventNewBasalProfile(nsProfile));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -419,7 +419,8 @@ public class DataService extends IntentService {
|
|||
if (trJson.has("eventType")) {
|
||||
treatment.mealBolus = true;
|
||||
if (trJson.get("eventType").equals("Correction Bolus")) treatment.mealBolus = false;
|
||||
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0) treatment.mealBolus = false;
|
||||
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0)
|
||||
treatment.mealBolus = false;
|
||||
}
|
||||
treatment.setTimeIndex(treatment.getTimeIndex());
|
||||
try {
|
||||
|
@ -469,7 +470,8 @@ public class DataService extends IntentService {
|
|||
if (trJson.has("eventType")) {
|
||||
treatment.mealBolus = true;
|
||||
if (trJson.get("eventType").equals("Correction Bolus")) treatment.mealBolus = false;
|
||||
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0) treatment.mealBolus = false;
|
||||
if (trJson.get("eventType").equals("Bolus Wizard") && treatment.carbs <= 0)
|
||||
treatment.mealBolus = false;
|
||||
}
|
||||
treatment.setTimeIndex(treatment.getTimeIndex());
|
||||
try {
|
||||
|
|
|
@ -32,7 +32,7 @@ public class BgReading implements DataPointInterface {
|
|||
public double value;
|
||||
|
||||
@DatabaseField
|
||||
public double slope;
|
||||
public String direction;
|
||||
|
||||
@DatabaseField
|
||||
public double raw;
|
||||
|
@ -48,6 +48,7 @@ public class BgReading implements DataPointInterface {
|
|||
timeIndex = sgv.getMills();
|
||||
value = sgv.getMgdl();
|
||||
raw = sgv.getFiltered();
|
||||
direction = sgv.getDirection();
|
||||
}
|
||||
|
||||
public Double valueToUnits(String units) {
|
||||
|
@ -62,13 +63,48 @@ public class BgReading implements DataPointInterface {
|
|||
else return DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL);
|
||||
}
|
||||
|
||||
public String directionToSymbol() {
|
||||
String symbol = "";
|
||||
if (direction.compareTo("DoubleDown") == 0) {
|
||||
symbol = "\u21ca";
|
||||
} else if (direction.compareTo("SingleDown") == 0) {
|
||||
symbol = "\u2193";
|
||||
} else if (direction.compareTo("FortyFiveDown") == 0) {
|
||||
symbol = "\u2198";
|
||||
} else if (direction.compareTo("Flat") == 0) {
|
||||
symbol = "\u2192";
|
||||
} else if (direction.compareTo("FortyFiveUp") == 0) {
|
||||
symbol = "\u2197";
|
||||
} else if (direction.compareTo("SingleUp") == 0) {
|
||||
symbol = "\u2191";
|
||||
} else if (direction.compareTo("DoubleUp") == 0) {
|
||||
symbol = "\u21c8";
|
||||
} else if (isSlopeNameInvalid(direction)) {
|
||||
symbol = "??";
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public static boolean isSlopeNameInvalid(String direction) {
|
||||
if (direction.compareTo("NOT_COMPUTABLE") == 0 ||
|
||||
direction.compareTo("NOT COMPUTABLE") == 0 ||
|
||||
direction.compareTo("OUT_OF_RANGE") == 0 ||
|
||||
direction.compareTo("OUT OF RANGE") == 0 ||
|
||||
direction.compareTo("NONE") == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BgReading{" +
|
||||
"timeIndex=" + timeIndex +
|
||||
", date=" + new Date(timeIndex) +
|
||||
", value=" + value +
|
||||
", slope=" + slope +
|
||||
", direction=" + direction +
|
||||
", raw=" + raw +
|
||||
", battery_level=" + battery_level +
|
||||
'}';
|
||||
|
|
|
@ -40,7 +40,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
public static final String DATABASE_TREATMENTS = "Treatments";
|
||||
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
|
||||
|
||||
private static final int DATABASE_VERSION = 4;
|
||||
private static final int DATABASE_VERSION = 5;
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
|
@ -196,8 +196,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", true);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("timeIndex", mills);
|
||||
queryBuilder.where().gt("value", 38);
|
||||
where.ge("timeIndex", mills).and().gt("value", 38);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
bgReadings = daoBgreadings.query(preparedQuery);
|
||||
return bgReadings;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
/**
|
||||
* Created by mike on 13.12.2016.
|
||||
*/
|
||||
|
||||
public class EventInitializationChanged {
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
/**
|
||||
* Created by mike on 08.12.2016.
|
||||
*/
|
||||
|
||||
public class PumpDescription {
|
||||
public static final int NONE = 0;
|
||||
public static final int PERCENT = 1;
|
||||
public static final int ABSOLUTE = 2;
|
||||
public static final int EXTENDED = 4;
|
||||
|
||||
public boolean isBolusCapable = true;
|
||||
public double bolusStep = 0.1d;
|
||||
|
||||
public boolean isExtendedBolusCapable = true;
|
||||
public double extendedBolusStep = 0.1d;
|
||||
|
||||
public boolean isTempBasalCapable = true;
|
||||
public int lowTempBasalStyle = PERCENT;
|
||||
public int highTempBasalStyle = PERCENT;
|
||||
public double maxHighTempPercent = 200;
|
||||
public double maxHighTempAbsolute = 0; // zero = no limit
|
||||
public double lowTempPercentStep = 10;
|
||||
public double lowTempAbsoluteStep = 0.05d;
|
||||
public int lowTempPercentDuration = 30;
|
||||
public int lowTempAbsoluteDuration = 30;
|
||||
public double highTempPercentStep = 10;
|
||||
public double highTempAbsoluteStep = 0.05d;
|
||||
public int highTempPercentDuration = 30;
|
||||
public int highTempAbsoluteDuration = 30;
|
||||
|
||||
public boolean isSetBasalProfileCapable = true;
|
||||
public double basalStep = 0.01d;
|
||||
public double basalMinimumRate = 0.04d;
|
||||
|
||||
public boolean isRefillingCapable = false;
|
||||
}
|
|
@ -22,7 +22,11 @@ public interface PumpInterface {
|
|||
boolean isExtendedBoluslInProgress();
|
||||
|
||||
// Upload to pump new basal profile
|
||||
void setNewBasalProfile(NSProfile profile);
|
||||
int SUCCESS = 0;
|
||||
int FAILED = 1;
|
||||
int NOT_NEEDED = 2;
|
||||
int setNewBasalProfile(NSProfile profile);
|
||||
boolean isThisProfileSet(NSProfile profile);
|
||||
|
||||
double getBaseBasalRate(); // base basal rate, not temp basal
|
||||
double getTempBasalAbsoluteRate();
|
||||
|
@ -42,4 +46,6 @@ public interface PumpInterface {
|
|||
// Status to be passed to NS
|
||||
JSONObject getJSONStatus();
|
||||
String deviceID();
|
||||
|
||||
PumpDescription getPumpDescription();
|
||||
}
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
package info.nightscout.androidaps.plugins.Actions;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog;
|
||||
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
||||
|
@ -22,10 +29,16 @@ import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog;
|
|||
public class ActionsFragment extends Fragment implements FragmentBase, View.OnClickListener {
|
||||
|
||||
static ActionsPlugin actionsPlugin = new ActionsPlugin();
|
||||
|
||||
static public ActionsPlugin getPlugin() {
|
||||
return actionsPlugin;
|
||||
}
|
||||
|
||||
Button profileSwitch;
|
||||
Button extendedBolus;
|
||||
Button tempBasal;
|
||||
Button fill;
|
||||
|
||||
public ActionsFragment() {
|
||||
}
|
||||
|
||||
|
@ -35,14 +48,69 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl
|
|||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.actions_fragment, container, false);
|
||||
|
||||
view.findViewById(R.id.actions_profileswitch).setOnClickListener(this);
|
||||
view.findViewById(R.id.actions_extendedbolus).setOnClickListener(this);
|
||||
view.findViewById(R.id.actions_settempbasal).setOnClickListener(this);
|
||||
view.findViewById(R.id.actions_fill).setOnClickListener(this);
|
||||
profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch);
|
||||
extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus);
|
||||
tempBasal = (Button) view.findViewById(R.id.actions_settempbasal);
|
||||
fill = (Button) view.findViewById(R.id.actions_fill);
|
||||
|
||||
profileSwitch.setOnClickListener(this);
|
||||
extendedBolus.setOnClickListener(this);
|
||||
tempBasal.setOnClickListener(this);
|
||||
fill.setOnClickListener(this);
|
||||
|
||||
updateGUIIfVisible();
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MainApp.bus().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventInitializationChanged ev) {
|
||||
updateGUIIfVisible();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventRefreshGui ev) {
|
||||
updateGUIIfVisible();
|
||||
}
|
||||
|
||||
void updateGUIIfVisible() {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
profileSwitch.setVisibility(View.GONE);
|
||||
else
|
||||
profileSwitch.setVisibility(View.VISIBLE);
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
extendedBolus.setVisibility(View.GONE);
|
||||
else
|
||||
extendedBolus.setVisibility(View.VISIBLE);
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
tempBasal.setVisibility(View.GONE);
|
||||
else
|
||||
tempBasal.setVisibility(View.VISIBLE);
|
||||
if (!MainApp.getConfigBuilder().getPumpDescription().isRefillingCapable || !MainApp.getConfigBuilder().isInitialized())
|
||||
fill.setVisibility(View.GONE);
|
||||
else
|
||||
fill.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
FragmentManager manager = getFragmentManager();
|
||||
|
|
|
@ -30,12 +30,12 @@ public class ActionsPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,12 +45,12 @@ public class ActionsPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
|
|||
|
||||
public class CareportalFragment extends Fragment implements FragmentBase, View.OnClickListener {
|
||||
|
||||
static CareportalPlugin careportalPlugin = new CareportalPlugin();
|
||||
static CareportalPlugin careportalPlugin;
|
||||
|
||||
static public CareportalPlugin getPlugin() {
|
||||
if (careportalPlugin == null) {
|
||||
careportalPlugin = new CareportalPlugin();
|
||||
}
|
||||
return careportalPlugin;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,12 @@ public class CareportalPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,12 +41,12 @@ public class CareportalPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -541,7 +541,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
builder.setMessage(confirmText);
|
||||
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||
if (options.executeProfileSwitch) {
|
||||
if (data.has("profile")) {
|
||||
sHandler.post(new Runnable() {
|
||||
|
@ -559,12 +558,15 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
} else {
|
||||
log.error("No active pump selected");
|
||||
}
|
||||
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -69,12 +69,12 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == PROFILE && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,12 +84,12 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == PROFILE) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == PROFILE) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
void storeSettings() {
|
||||
|
@ -265,7 +265,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
|
|||
if (percentage < MIN_PERCENTAGE || percentage > MAX_PERCENTAGE){
|
||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage");
|
||||
log.error(msg);
|
||||
OpenAPSMAPlugin.sendErrorToNSClient(msg);
|
||||
MainApp.getConfigBuilder().uploadError(msg);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
||||
percentage = Math.max(percentage, MIN_PERCENTAGE);
|
||||
percentage = Math.min(percentage, MAX_PERCENTAGE);
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
package info.nightscout.androidaps.plugins.ConfigBuilder;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -21,6 +15,7 @@ import android.widget.ListView;
|
|||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
|
@ -31,9 +26,8 @@ import info.nightscout.androidaps.interfaces.FragmentBase;
|
|||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopFragment;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
|
||||
|
||||
|
||||
public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
||||
|
@ -93,7 +87,8 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
nsclientVerView.setText(ConfigBuilderPlugin.nsClientVersionName);
|
||||
nightscoutVerView.setText(ConfigBuilderPlugin.nightscoutVersionName);
|
||||
if (ConfigBuilderPlugin.nsClientVersionCode < 117) nsclientVerView.setTextColor(Color.RED);
|
||||
if (ConfigBuilderPlugin.nightscoutVersionCode < 900) nightscoutVerView.setTextColor(Color.RED);
|
||||
if (ConfigBuilderPlugin.nightscoutVersionCode < 900)
|
||||
nightscoutVerView.setTextColor(Color.RED);
|
||||
setViews();
|
||||
return view;
|
||||
}
|
||||
|
@ -179,6 +174,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
onEnabledCategoryChanged(plugin, type);
|
||||
configBuilderPlugin.storeSettings();
|
||||
MainApp.bus().post(new EventRefreshGui(true));
|
||||
getPlugin().logPluginStatus();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -189,6 +185,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
plugin.setFragmentVisible(type, cb.isChecked());
|
||||
configBuilderPlugin.storeSettings();
|
||||
MainApp.bus().post(new EventRefreshGui(true));
|
||||
getPlugin().logPluginStatus();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -208,11 +205,13 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
holder.checkboxVisible.setEnabled(false);
|
||||
}
|
||||
|
||||
int type = plugin.getType();
|
||||
// Force enabled if there is only one plugin
|
||||
// Hide enabled control and force enabled plugin if there is only one plugin available
|
||||
if (type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE)
|
||||
if (pluginList.size() < 2)
|
||||
if (pluginList.size() < 2) {
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
plugin.setFragmentEnabled(type, true);
|
||||
getPlugin().storeSettings();
|
||||
}
|
||||
|
||||
// Constraints cannot be disabled
|
||||
if (type == PluginBase.CONSTRAINTS)
|
||||
|
@ -228,6 +227,16 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
}
|
||||
|
||||
// Disable profile control for pump profiles if pump is not enabled
|
||||
if (type == PluginBase.PROFILE) {
|
||||
if (PumpInterface.class.isAssignableFrom(plugin.getClass())) {
|
||||
if (!plugin.isEnabled(PluginBase.PUMP)) {
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
holder.checkboxEnabled.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return convertView;
|
||||
|
||||
}
|
||||
|
@ -235,9 +244,8 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
|
||||
void onEnabledCategoryChanged(PluginBase changedPlugin, int type) {
|
||||
int category = changedPlugin.getType();
|
||||
ArrayList<PluginBase> pluginsInCategory = null;
|
||||
switch (category) {
|
||||
switch (type) {
|
||||
// Multiple selection allowed
|
||||
case PluginBase.GENERAL:
|
||||
case PluginBase.CONSTRAINTS:
|
||||
|
@ -256,7 +264,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
case PluginBase.TEMPBASAL:
|
||||
case PluginBase.TREATMENT:
|
||||
case PluginBase.PUMP:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsList(category);
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class);
|
||||
break;
|
||||
}
|
||||
if (pluginsInCategory != null) {
|
||||
|
@ -271,6 +279,11 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
}
|
||||
} else { // enable first plugin in list
|
||||
if (type == PluginBase.PUMP)
|
||||
MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true);
|
||||
else if (type == PluginBase.PROFILE)
|
||||
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true);
|
||||
else
|
||||
pluginsInCategory.get(0).setFragmentEnabled(type, true);
|
||||
}
|
||||
setViews();
|
||||
|
|
|
@ -35,6 +35,7 @@ import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
|||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.TempBasalsInterface;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
|
@ -45,6 +46,10 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
|||
import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResult;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
||||
import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.client.data.DbLogger;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
@ -97,12 +102,12 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return true;
|
||||
return type == GENERAL && true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return true;
|
||||
return type == GENERAL && true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -191,6 +196,22 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
return activeLoop;
|
||||
}
|
||||
|
||||
public void logPluginStatus() {
|
||||
for (PluginBase p : pluginList) {
|
||||
log.debug(p.getName() + ":" +
|
||||
(p.isEnabled(1) ? " GENERAL" : "") +
|
||||
(p.isEnabled(2) ? " TREATMENT" : "") +
|
||||
(p.isEnabled(3) ? " TEMPBASAL" : "") +
|
||||
(p.isEnabled(4) ? " PROFILE" : "") +
|
||||
(p.isEnabled(5) ? " APS" : "") +
|
||||
(p.isEnabled(6) ? " PUMP" : "") +
|
||||
(p.isEnabled(7) ? " CONSTRAINTS" : "") +
|
||||
(p.isEnabled(8) ? " LOOP" : "") +
|
||||
(p.isEnabled(9) ? " BGSOURCE" : "")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifySelectionInCategories() {
|
||||
ArrayList<PluginBase> pluginsInCategory;
|
||||
|
||||
|
@ -314,8 +335,31 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setNewBasalProfile(NSProfile profile) {
|
||||
activePump.setNewBasalProfile(profile);
|
||||
public int setNewBasalProfile(NSProfile profile) {
|
||||
// Compare with pump limits
|
||||
NSProfile.BasalValue[] basalValues = profile.getBasalValues();
|
||||
|
||||
for (int index = 0; index < basalValues.length; index++) {
|
||||
if (basalValues[index].value < getPumpDescription().basalMinimumRate) {
|
||||
Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.sResources.getString(R.string.basalvaluebelowminimum), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM));
|
||||
|
||||
if (isThisProfileSet(profile)) {
|
||||
log.debug("Correct profile already set");
|
||||
return NOT_NEEDED;
|
||||
} else {
|
||||
return activePump.setNewBasalProfile(profile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThisProfileSet(NSProfile profile) {
|
||||
return activePump.isThisProfileSet(profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -594,6 +638,21 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
|
|||
else return "Unknown";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpDescription getPumpDescription() {
|
||||
if (activePump != null)
|
||||
return activePump.getPumpDescription();
|
||||
else {
|
||||
PumpDescription emptyDescription = new PumpDescription();
|
||||
emptyDescription.isBolusCapable = false;
|
||||
emptyDescription.isExtendedBolusCapable = false;
|
||||
emptyDescription.isSetBasalProfileCapable = false;
|
||||
emptyDescription.isTempBasalCapable = false;
|
||||
emptyDescription.isRefillingCapable = false;
|
||||
return emptyDescription;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraints interface
|
||||
**/
|
||||
|
|
|
@ -38,9 +38,12 @@ import info.nightscout.utils.SetWarnColor;
|
|||
public class DanaRFragment extends Fragment implements FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRFragment.class);
|
||||
|
||||
private static DanaRPlugin danaRPlugin = new DanaRPlugin();
|
||||
private static DanaRPlugin danaRPlugin;
|
||||
|
||||
public static DanaRPlugin getPlugin() {
|
||||
if(danaRPlugin==null){
|
||||
danaRPlugin = new DanaRPlugin();
|
||||
}
|
||||
return danaRPlugin;
|
||||
}
|
||||
|
||||
|
@ -204,20 +207,20 @@ public class DanaRFragment extends Fragment implements FragmentBase {
|
|||
Long agoMsec = new Date().getTime() - DanaRPlugin.getDanaRPump().lastBolusTime.getTime();
|
||||
double agoHours = agoMsec / 60d / 60d / 1000d;
|
||||
if (agoHours < 6) // max 6h back
|
||||
lastBolusView.setText(formatTime.format(DanaRPlugin.getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(danaRPlugin.getDanaRPump().lastBolusAmount) + " U");
|
||||
lastBolusView.setText(formatTime.format(DanaRPlugin.getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getPlugin().getDanaRPump().lastBolusAmount) + " U");
|
||||
else lastBolusView.setText("");
|
||||
}
|
||||
|
||||
dailyUnitsView.setText(DecimalFormatter.to0Decimal(DanaRPlugin.getDanaRPump().dailyTotalUnits) + " / " + DanaRPlugin.getDanaRPump().maxDailyTotalUnits + " U");
|
||||
SetWarnColor.setColor(dailyUnitsView, DanaRPlugin.getDanaRPump().dailyTotalUnits, DanaRPlugin.getDanaRPump().maxDailyTotalUnits * 0.75d, DanaRPlugin.getDanaRPump().maxDailyTotalUnits * 0.9d);
|
||||
basaBasalRateView.setText("( " + (DanaRPlugin.getDanaRPump().activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(danaRPlugin.getBaseBasalRate()) + " U/h");
|
||||
if (danaRPlugin.isRealTempBasalInProgress()) {
|
||||
tempBasalView.setText(danaRPlugin.getRealTempBasal().toString());
|
||||
basaBasalRateView.setText("( " + (DanaRPlugin.getDanaRPump().activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(getPlugin().getBaseBasalRate()) + " U/h");
|
||||
if (getPlugin().isRealTempBasalInProgress()) {
|
||||
tempBasalView.setText(getPlugin().getRealTempBasal().toString());
|
||||
} else {
|
||||
tempBasalView.setText("");
|
||||
}
|
||||
if (danaRPlugin.isExtendedBoluslInProgress()) {
|
||||
extendedBolusView.setText(danaRPlugin.getExtendedBolus().toString());
|
||||
if (getPlugin().isExtendedBoluslInProgress()) {
|
||||
extendedBolusView.setText(getPlugin().getExtendedBolus().toString());
|
||||
} else {
|
||||
extendedBolusView.setText("");
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.json.JSONObject;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -33,14 +32,18 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
|
|||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
|
@ -63,6 +66,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
private static DanaRPump sDanaRPump = new DanaRPump();
|
||||
private static boolean useExtendedBoluses = false;
|
||||
|
||||
private static PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
public static DanaRPump getDanaRPump() {
|
||||
return sDanaRPump;
|
||||
}
|
||||
|
@ -75,6 +80,32 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
Intent intent = new Intent(context, ExecutionService.class);
|
||||
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
MainApp.bus().register(this);
|
||||
|
||||
pumpDescription.isBolusCapable = true; // TODO: use description in setTempBasalAbsolute
|
||||
pumpDescription.bolusStep = 0.05d;
|
||||
|
||||
pumpDescription.isExtendedBolusCapable = true;
|
||||
pumpDescription.extendedBolusStep = 0.1d;
|
||||
|
||||
pumpDescription.isTempBasalCapable = true;
|
||||
pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT;
|
||||
pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT;
|
||||
pumpDescription.maxHighTempPercent = 200;
|
||||
pumpDescription.maxHighTempAbsolute = 0;
|
||||
pumpDescription.lowTempPercentStep = 10;
|
||||
pumpDescription.lowTempAbsoluteStep = 0;
|
||||
pumpDescription.lowTempPercentDuration = 60;
|
||||
pumpDescription.lowTempAbsoluteDuration = 60;
|
||||
pumpDescription.highTempPercentStep = 10;
|
||||
pumpDescription.highTempAbsoluteStep = 0.05d;
|
||||
pumpDescription.highTempPercentDuration = 60;
|
||||
pumpDescription.highTempAbsoluteDuration = 30;
|
||||
|
||||
pumpDescription.isSetBasalProfileCapable = true;
|
||||
pumpDescription.basalStep = 0.01d;
|
||||
pumpDescription.basalMinimumRate = 0.04d;
|
||||
|
||||
pumpDescription.isRefillingCapable = true;
|
||||
}
|
||||
|
||||
ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
@ -99,13 +130,18 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventPreferenceChange s) {
|
||||
if (isEnabled(PUMP)) {
|
||||
boolean previousValue = useExtendedBoluses;
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false);
|
||||
|
||||
pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT;
|
||||
|
||||
if (useExtendedBoluses != previousValue && isExtendedBoluslInProgress()) {
|
||||
sExecutionService.extendedBolusStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin base interface
|
||||
@Override
|
||||
|
@ -140,8 +176,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == PluginBase.PROFILE) this.fragmentProfileEnabled = fragmentEnabled;
|
||||
else if (type == PluginBase.PUMP) this.fragmentPumpEnabled = fragmentEnabled;
|
||||
if (type == PluginBase.PROFILE)
|
||||
this.fragmentProfileEnabled = fragmentEnabled;
|
||||
else if (type == PluginBase.PUMP)
|
||||
this.fragmentPumpEnabled = fragmentEnabled;
|
||||
// if pump profile was enabled need to switch to another too
|
||||
if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) {
|
||||
setFragmentEnabled(PluginBase.PROFILE, false);
|
||||
setFragmentVisible(PluginBase.PROFILE, false);
|
||||
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(PluginBase.PROFILE, true);
|
||||
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentVisible(PluginBase.PROFILE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,7 +197,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return getDanaRPump().lastConnection.getTime() > 0;
|
||||
return getDanaRPump().lastConnection.getTime() > 0 && getDanaRPump().isExtendedBolusEnabled;
|
||||
}
|
||||
|
||||
// Pump interface
|
||||
|
@ -173,13 +218,46 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setNewBasalProfile(NSProfile profile) {
|
||||
public int setNewBasalProfile(NSProfile profile) {
|
||||
if (sExecutionService == null) {
|
||||
log.error("setNewBasalProfile sExecutionService is null");
|
||||
return;
|
||||
return FAILED;
|
||||
}
|
||||
if (!sExecutionService.updateBasalsInPump(profile))
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.failedupdatebasalprofile));
|
||||
if (!isInitialized()) {
|
||||
log.error("setNewBasalProfile not initialized");
|
||||
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
return FAILED;
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||
}
|
||||
if (!sExecutionService.updateBasalsInPump(profile)) {
|
||||
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
return FAILED;
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThisProfileSet(NSProfile profile) {
|
||||
if (!isInitialized())
|
||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||
DanaRPump pump = getDanaRPump();
|
||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
||||
Double profileValue = profile.getBasal(h * basalIncrement);
|
||||
if (!pumpValue.equals(profileValue)) {
|
||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -585,6 +663,10 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
return sExecutionService != null && sExecutionService.isConnecting();
|
||||
}
|
||||
|
||||
public static void doDisconnect(String from) {
|
||||
if (sExecutionService != null) sExecutionService.disconnect(from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getJSONStatus() {
|
||||
if (getDanaRPump().lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) {
|
||||
|
@ -611,7 +693,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
extended.put("BaseBasalRate", getBaseBasalRate());
|
||||
try {
|
||||
extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile());
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
pump.put("battery", battery);
|
||||
pump.put("status", status);
|
||||
|
@ -629,6 +712,11 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf
|
|||
return getDanaRPump().serialNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpDescription getPumpDescription() {
|
||||
return pumpDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraint interface
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,11 @@ public class DanaRPump {
|
|||
public static final int UNITS_MGDL = 0;
|
||||
public static final int UNITS_MMOL = 1;
|
||||
|
||||
public static final int DELIVERY_PRIME = 0x01;
|
||||
public static final int DELIVERY_STEP_BOLUS = 0x02;
|
||||
public static final int DELIVERY_BASAL = 0x04;
|
||||
public static final int DELIVERY_EXT_BOLUS = 0x08;
|
||||
|
||||
public static final String PROFILE_PREFIX = "DanaR-";
|
||||
|
||||
public Date lastConnection = new Date(0);
|
||||
|
@ -35,12 +40,25 @@ public class DanaRPump {
|
|||
public int password = -1;
|
||||
public Date pumpTime = new Date(0);
|
||||
|
||||
public static final int DOMESTIC_MODEL = 0x01;
|
||||
public static final int EXPORT_MODEL = 0x03;
|
||||
public int model;
|
||||
public int protocol;
|
||||
public int productCode;
|
||||
|
||||
public boolean isConfigUD;
|
||||
public boolean isExtendedBolusEnabled;
|
||||
|
||||
|
||||
// Status
|
||||
public boolean pumpSuspended;
|
||||
public boolean calculatorEnabled;
|
||||
public double dailyTotalUnits;
|
||||
public int maxDailyTotalUnits;
|
||||
|
||||
public double bolusStep;
|
||||
public double basalStep;
|
||||
|
||||
public double iob;
|
||||
|
||||
public double reservoirRemainingUnits;
|
||||
|
@ -58,6 +76,7 @@ public class DanaRPump {
|
|||
public int tempBasalTotalSec;
|
||||
public Date tempBasalStart;
|
||||
|
||||
public boolean isDualBolusInProgress;
|
||||
public boolean isExtendedInProgress;
|
||||
public int extendedBolusMinutes;
|
||||
public double extendedBolusAmount;
|
||||
|
|
|
@ -30,6 +30,7 @@ import info.nightscout.androidaps.MainApp;
|
|||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
|
@ -58,8 +59,10 @@ import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart;
|
|||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTime;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingActiveProfile;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingBasal;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingMeal;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingGlucose;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingMaxValues;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingProfileRatios;
|
||||
|
@ -174,6 +177,11 @@ public class ExecutionService extends Service {
|
|||
return connectionInProgress;
|
||||
}
|
||||
|
||||
public void disconnect(String from) {
|
||||
if (mSerialIOThread != null)
|
||||
mSerialIOThread.disconnect(from);
|
||||
}
|
||||
|
||||
public void connect(String from) {
|
||||
if (danaRPump.password != -1 && danaRPump.password != SafeParse.stringToInt(SP.getString("danar_password", "-1"))) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
||||
|
@ -270,11 +278,11 @@ public class ExecutionService extends Service {
|
|||
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||
|
||||
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
|
||||
mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
|
||||
mSerialIOThread.sendMessage(exStatusMsg);
|
||||
mSerialIOThread.sendMessage(statusMsg);
|
||||
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
|
||||
|
||||
if (danaRPump.isNewPump) {
|
||||
mSerialIOThread.sendMessage(new MsgCheckValue());
|
||||
|
@ -303,10 +311,10 @@ public class ExecutionService extends Service {
|
|||
}
|
||||
|
||||
Date now = new Date();
|
||||
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime()) {
|
||||
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).isInitialized()) {
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
||||
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
|
||||
//0x3203
|
||||
mSerialIOThread.sendMessage(new MsgSettingMeal());
|
||||
mSerialIOThread.sendMessage(new MsgSettingBasal());
|
||||
//0x3201
|
||||
mSerialIOThread.sendMessage(new MsgSettingMaxValues());
|
||||
|
@ -315,11 +323,13 @@ public class ExecutionService extends Service {
|
|||
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
|
||||
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
|
||||
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
|
||||
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
|
||||
danaRPump.lastSettingsRead = now;
|
||||
}
|
||||
|
||||
danaRPump.lastConnection = now;
|
||||
MainApp.bus().post(new EventDanaRNewStatus());
|
||||
MainApp.bus().post(new EventInitializationChanged());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -361,8 +371,8 @@ public class ExecutionService extends Service {
|
|||
public boolean bolus(Double amount, int carbs, Treatment t) {
|
||||
bolusingTreatment = t;
|
||||
MsgBolusStart start = new MsgBolusStart(amount);
|
||||
MsgBolusProgress progress = new MsgBolusProgress(MainApp.bus(), amount, t);
|
||||
MsgBolusStop stop = new MsgBolusStop(MainApp.bus(), amount, t);
|
||||
MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables
|
||||
MsgBolusStop stop = new MsgBolusStop(amount, t);
|
||||
|
||||
connect("bolus");
|
||||
if (!isConnected()) return false;
|
||||
|
@ -381,6 +391,11 @@ public class ExecutionService extends Service {
|
|||
}
|
||||
while (!stop.stopped && !start.failed) {
|
||||
waitMsec(100);
|
||||
if (progress.lastReceive != 0 && (new Date().getTime() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm
|
||||
stop.stopped = true;
|
||||
stop.forced = true;
|
||||
log.debug("Communication stopped");
|
||||
}
|
||||
}
|
||||
waitMsec(300);
|
||||
bolusingTreatment = null;
|
||||
|
@ -466,6 +481,7 @@ public class ExecutionService extends Service {
|
|||
mSerialIOThread.sendMessage(msgSet);
|
||||
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
|
||||
mSerialIOThread.sendMessage(msgActivate);
|
||||
danaRPump.lastSettingsRead = new Date(0); // force read full settings
|
||||
getPumpStatus();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,15 @@ public class MessageBase {
|
|||
AddParamByte((byte) (date.get(Calendar.MINUTE)));
|
||||
}
|
||||
|
||||
public void AddParamDateTime(Date date) {
|
||||
AddParamByte((byte) (date.getSeconds()));
|
||||
AddParamByte((byte) (date.getMinutes()));
|
||||
AddParamByte((byte) (date.getHours()));
|
||||
AddParamByte((byte) (date.getDate()));
|
||||
AddParamByte((byte) (date.getMonth() + 1));
|
||||
AddParamByte((byte) (date.getYear() - 100));
|
||||
}
|
||||
|
||||
public byte[] getRawMessageBytes() {
|
||||
this.buffer[0] = (byte) 0x7E;
|
||||
this.buffer[1] = (byte) 0x7E;
|
||||
|
|
|
@ -47,6 +47,7 @@ public class MessageHashTable {
|
|||
put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR
|
||||
put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED
|
||||
put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I
|
||||
put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I
|
||||
put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I
|
||||
put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I
|
||||
put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL
|
||||
|
@ -56,6 +57,7 @@ public class MessageHashTable {
|
|||
put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS
|
||||
put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER
|
||||
put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE
|
||||
put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S
|
||||
put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S
|
||||
put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S
|
||||
put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE
|
||||
|
|
|
@ -62,7 +62,7 @@ public class MessageOriginalNames {
|
|||
messageNames.put(0x320d, "CMD_SETTING_V_CIR_CF_VALUE");
|
||||
|
||||
messageNames.put(0x3301, "CMD_SETTING_MEAL_INS_S");
|
||||
messageNames.put(0x3302, "CMD_SETTING_Based_INS_S");
|
||||
messageNames.put(0x3302, "CMD_SETTING_BASAL_INS_S");
|
||||
messageNames.put(0x3303, "CMD_SETTING_MEAL_SETTING_S");
|
||||
messageNames.put(0x3304, "CMD_SETTING_CCC_S");
|
||||
messageNames.put(0x3305, "CMD_SETTING_MAX_VALUE_S");
|
||||
|
|
|
@ -5,6 +5,8 @@ import com.squareup.otto.Bus;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
@ -13,27 +15,28 @@ import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProg
|
|||
|
||||
public class MsgBolusProgress extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgBolusProgress.class);
|
||||
private static Bus bus = null;
|
||||
|
||||
private static Treatment t;
|
||||
private static double amount;
|
||||
|
||||
public static long lastReceive = 0;
|
||||
public int progress = -1;
|
||||
|
||||
public MsgBolusProgress() {
|
||||
SetCommand(0x0202);
|
||||
}
|
||||
|
||||
public MsgBolusProgress(Bus bus, double amount, Treatment t) {
|
||||
public MsgBolusProgress(double amount, Treatment t) {
|
||||
this();
|
||||
this.amount = amount;
|
||||
this.t = t;
|
||||
this.bus = bus;
|
||||
lastReceive = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
progress = intFromBuff(bytes, 0, 2);
|
||||
lastReceive = new Date().getTime();
|
||||
Double done = (amount * 100 - progress) / 100d;
|
||||
t.insulin = done;
|
||||
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||
|
@ -45,6 +48,6 @@ public class MsgBolusProgress extends MessageBase {
|
|||
log.debug("Bolus remaining: " + progress + " delivered: " + done);
|
||||
}
|
||||
|
||||
bus.post(bolusingEvent);
|
||||
MainApp.bus().post(bolusingEvent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ public class MsgBolusStart extends MessageBase {
|
|||
if (amount > BuildConfig.MAXBOLUS) amount = BuildConfig.MAXBOLUS;
|
||||
|
||||
AddParamInt((int) (amount * 100));
|
||||
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Bolus start : " + amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,7 +14,6 @@ public class MsgBolusStop extends MessageBase {
|
|||
private static Logger log = LoggerFactory.getLogger(MsgBolusStop.class);
|
||||
private static Treatment t;
|
||||
private static Double amount;
|
||||
private static Bus bus = null;
|
||||
|
||||
public static boolean stopped = false;
|
||||
public static boolean forced = false;
|
||||
|
@ -24,9 +23,8 @@ public class MsgBolusStop extends MessageBase {
|
|||
stopped = false;
|
||||
}
|
||||
|
||||
public MsgBolusStop(Bus bus, Double amount, Treatment t) {
|
||||
public MsgBolusStop(Double amount, Treatment t) {
|
||||
this();
|
||||
this.bus = bus;
|
||||
this.t = t;
|
||||
this.amount = amount;
|
||||
forced = false;
|
||||
|
@ -43,6 +41,6 @@ public class MsgBolusStop extends MessageBase {
|
|||
} else {
|
||||
bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusprogress_stoped);
|
||||
}
|
||||
bus.post(bolusingEvent);
|
||||
MainApp.bus().post(bolusingEvent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* Created by mike on 30.06.2016.
|
||||
|
@ -17,15 +22,22 @@ public class MsgCheckValue extends MessageBase {
|
|||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
int a = intFromBuff(bytes, 0, 1);
|
||||
int b = intFromBuff(bytes, 1, 1);
|
||||
if (a != 3 || b <= 0) {
|
||||
// another message will follow
|
||||
} else {
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
|
||||
pump.model = intFromBuff(bytes, 0, 1);
|
||||
pump.protocol = intFromBuff(bytes, 1, 1);
|
||||
pump.productCode = intFromBuff(bytes, 2, 1);
|
||||
if (pump.model != DanaRPump.EXPORT_MODEL) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error);
|
||||
((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model");
|
||||
log.debug("Wrong model selected");
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Model: " + String.format("%02X ", pump.model));
|
||||
log.debug("Protocol: " + String.format("%02X ", pump.protocol));
|
||||
log.debug("Product Code: " + String.format("%02X ", pump.productCode));
|
||||
}
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Response: " + String.format("%02X ", a) + String.format("%02X ", b));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,10 +31,6 @@ public class MsgError extends MessageBase {
|
|||
break;
|
||||
case 5: // Occlusion
|
||||
errorString = MainApp.sResources.getString(R.string.occlusion);
|
||||
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||
MsgBolusStop.stopped = true;
|
||||
bolusingEvent.status = errorString;
|
||||
MainApp.bus().post(bolusingEvent);
|
||||
break;
|
||||
case 7: // Low Battery
|
||||
errorString = MainApp.sResources.getString(R.string.lowbattery);
|
||||
|
@ -43,6 +39,13 @@ public class MsgError extends MessageBase {
|
|||
errorString = MainApp.sResources.getString(R.string.batterydischarged);
|
||||
break;
|
||||
}
|
||||
|
||||
if (errorCode < 8) { // bolus delivering stopped
|
||||
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||
MsgBolusStop.stopped = true;
|
||||
bolusingEvent.status = errorString;
|
||||
MainApp.bus().post(bolusingEvent);
|
||||
}
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Error detected: " + errorString);
|
||||
MainApp.getConfigBuilder().uploadError(errorString);
|
||||
|
|
|
@ -3,6 +3,10 @@ package info.nightscout.androidaps.plugins.DanaR.comm;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
|
||||
public class MsgInitConnStatusBasic extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic.class);
|
||||
|
||||
|
@ -12,25 +16,51 @@ public class MsgInitConnStatusBasic extends MessageBase {
|
|||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
int a = intFromBuff(bytes, 0, 1);
|
||||
int b = intFromBuff(bytes, 1, 1);
|
||||
int c = intFromBuff(bytes, 2, 1);
|
||||
int d = intFromBuff(bytes, 3, 1);
|
||||
int e = intFromBuff(bytes, 4, 1);
|
||||
int f = intFromBuff(bytes, 5, 1);
|
||||
int g = intFromBuff(bytes, 6, 1);
|
||||
int h = intFromBuff(bytes, 7, 1);
|
||||
int i = intFromBuff(bytes, 8, 1);
|
||||
int j = intFromBuff(bytes, 9, 1);
|
||||
int k = intFromBuff(bytes, 10, 1);
|
||||
int l = intFromBuff(bytes, 11, 1);
|
||||
int m = intFromBuff(bytes, 12, 1);
|
||||
int n = intFromBuff(bytes, 13, 1);
|
||||
int o;
|
||||
if (bytes.length - 10 < 21) {
|
||||
return;
|
||||
}
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1;
|
||||
pump.calculatorEnabled = intFromBuff(bytes, 1, 1) == 1;
|
||||
pump.dailyTotalUnits = intFromBuff(bytes, 2, 3) / 750d;
|
||||
pump.maxDailyTotalUnits = intFromBuff(bytes, 5, 2) / 100;
|
||||
pump.reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750d;
|
||||
pump.bolusBlocked = intFromBuff(bytes, 10, 1) == 1;
|
||||
pump.currentBasal = intFromBuff(bytes, 11, 2) / 100d;
|
||||
pump.tempBasalPercent = intFromBuff(bytes, 13, 1);
|
||||
pump.isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1;
|
||||
pump.isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1;
|
||||
int statusBasalUDOption = intFromBuff(bytes, 16, 1);
|
||||
pump.isDualBolusInProgress = intFromBuff(bytes, 17, 1) == 1;
|
||||
double extendedBolusRate = intFromBuff(bytes, 18, 2) / 100d;
|
||||
pump.batteryRemaining = intFromBuff(bytes, 20, 1);
|
||||
try {
|
||||
o = intFromBuff(bytes, 21, 1);
|
||||
} catch (Exception ex) {
|
||||
o = 0;
|
||||
int bolusConfig = intFromBuff(bytes, 21, 1);
|
||||
boolean deliveryPrime = (bolusConfig & DanaRPump.DELIVERY_PRIME) != 0;
|
||||
boolean deliveryStepBolus = (bolusConfig & DanaRPump.DELIVERY_STEP_BOLUS) != 0;
|
||||
boolean deliveryBasal = (bolusConfig & DanaRPump.DELIVERY_BASAL) != 0;
|
||||
boolean deliveryExtBolus = (bolusConfig & DanaRPump.DELIVERY_EXT_BOLUS) != 0;
|
||||
log.debug("Delivery prime: " + deliveryPrime);
|
||||
log.debug("Delivery step bolus: " + deliveryStepBolus);
|
||||
log.debug("Delivery basal: " + deliveryBasal);
|
||||
log.debug("Delivery ext bolus: " + deliveryExtBolus);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump suspended: " + pump.pumpSuspended);
|
||||
log.debug("Calculator enabled: " + pump.calculatorEnabled);
|
||||
log.debug("Daily total units: " + pump.dailyTotalUnits);
|
||||
log.debug("Max daily total units: " + pump.maxDailyTotalUnits);
|
||||
log.debug("Reservoir remaining units: " + pump.reservoirRemainingUnits);
|
||||
log.debug("Bolus blocked: " + pump.bolusBlocked);
|
||||
log.debug("Current basal: " + pump.currentBasal);
|
||||
log.debug("Current temp basal percent: " + pump.tempBasalPercent);
|
||||
log.debug("Is extended bolus running: " + pump.isExtendedInProgress);
|
||||
log.debug("statusBasalUDOption: " + statusBasalUDOption);
|
||||
log.debug("Is dual bolus running: " + pump.isDualBolusInProgress);
|
||||
log.debug("Extended bolus rate: " + extendedBolusRate);
|
||||
log.debug("Battery remaining: " + pump.batteryRemaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,15 @@ package info.nightscout.androidaps.plugins.DanaR.comm;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
|
||||
/**
|
||||
* Created by mike on 28.05.2016.
|
||||
*/
|
||||
|
@ -15,10 +24,28 @@ public class MsgInitConnStatusBolus extends MessageBase {
|
|||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
int a1 = intFromBuff(bytes, 0, 1);
|
||||
int a2 = intFromBuff(bytes, 1, 1);
|
||||
int c = intFromBuff(bytes, 8, 2);
|
||||
int d = c / 100;
|
||||
int e = intFromBuff(bytes, 10, 2);
|
||||
if (bytes.length - 10 > 12) {
|
||||
return;
|
||||
}
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
int bolusConfig = intFromBuff(bytes, 0, 1);
|
||||
pump.isExtendedBolusEnabled = (bolusConfig & 0x01) != 0;
|
||||
|
||||
pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d;
|
||||
pump.maxBolus = intFromBuff(bytes, 2, 2) / 100d;
|
||||
//int bolusRate = intFromBuff(bytes, 4, 8);
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Is Extended bolus enabled: " + pump.isExtendedBolusEnabled);
|
||||
log.debug("Bolus increment: " + pump.bolusStep);
|
||||
log.debug("Bolus max: " + pump.maxBolus);
|
||||
}
|
||||
|
||||
if (!pump.isExtendedBolusEnabled) {
|
||||
Notification notification = new Notification(Notification.EXTENDED_BOLUS_DISABLED, MainApp.sResources.getString(R.string.danar_enableextendedbolus), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,15 +18,15 @@ public class MsgInitConnStatusOption extends MessageBase {
|
|||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
int a = intFromBuff(bytes, 0, 1);
|
||||
int b = intFromBuff(bytes, 1, 1);
|
||||
int c = intFromBuff(bytes, 2, 1);
|
||||
int d = intFromBuff(bytes, 3, 1);
|
||||
int e = intFromBuff(bytes, 4, 1);
|
||||
int f = intFromBuff(bytes, 5, 1);
|
||||
int g = intFromBuff(bytes, 6, 1);
|
||||
int h = intFromBuff(bytes, 7, 1);
|
||||
int i = intFromBuff(bytes, 8, 1);
|
||||
int status1224Clock = intFromBuff(bytes, 0, 1);
|
||||
int isStatusButtonScroll = intFromBuff(bytes, 1, 1);
|
||||
int soundVibration = intFromBuff(bytes, 2, 1);
|
||||
int glucoseUnit = intFromBuff(bytes, 3, 1);
|
||||
int lcdTimeout = intFromBuff(bytes, 4, 1);
|
||||
int backlightgTimeout = intFromBuff(bytes, 5, 1);
|
||||
int languageOption = intFromBuff(bytes, 6, 1);
|
||||
int lowReservoirAlarmBoundary = intFromBuff(bytes, 7, 1);
|
||||
//int none = intFromBuff(bytes, 8, 1);
|
||||
if (bytes.length >= 21) {
|
||||
DanaRPlugin.getDanaRPump().password = intFromBuff(bytes, 9, 2) ^ 0x3463;
|
||||
if (Config.logDanaMessageDetail)
|
||||
|
|
|
@ -6,6 +6,14 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class MsgInitConnStatusTime extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime.class);
|
||||
|
@ -16,9 +24,32 @@ public class MsgInitConnStatusTime extends MessageBase {
|
|||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
Date time = dateTimeSecFromBuff(bytes, 0);
|
||||
if (bytes.length - 10 > 7) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error);
|
||||
((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model");
|
||||
log.debug("Wrong model selected. Switching to Korean DanaR");
|
||||
((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true);
|
||||
((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentVisible(PluginBase.PUMP, true);
|
||||
((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, false);
|
||||
((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, false);
|
||||
|
||||
if (Config.logDanaMessageDetail)
|
||||
//If profile coming from pump, switch it as well
|
||||
if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){
|
||||
(MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false);
|
||||
(MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true);
|
||||
}
|
||||
|
||||
MainApp.getConfigBuilder().storeSettings();
|
||||
MainApp.bus().post(new EventRefreshGui(false));
|
||||
return;
|
||||
}
|
||||
|
||||
Date time = dateTimeSecFromBuff(bytes, 0);
|
||||
int versionCode = intFromBuff(bytes, 6, 1);
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump time: " + time);
|
||||
log.debug("Version code: " + versionCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
|
||||
public class MsgSetBasalProfile extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSetBasalProfile.class);
|
||||
|
@ -29,9 +33,13 @@ public class MsgSetBasalProfile extends MessageBase {
|
|||
if (result != 1) {
|
||||
failed = true;
|
||||
log.debug("Set basal profile result: " + result + " FAILED!!!");
|
||||
Notification reportFail = new Notification(Notification.PROFILE_SET_FAILED, MainApp.sResources.getString(R.string.profile_set_failed), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(reportFail));
|
||||
} else {
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Set basal profile result: " + result);
|
||||
Notification reportOK = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60);
|
||||
MainApp.bus().post(new EventNewNotification(reportOK));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||
|
||||
import com.j256.ormlite.stmt.query.Not;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
|
||||
public class MsgSetSingleBasalProfile extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSetSingleBasalProfile.class);
|
||||
|
||||
public MsgSetSingleBasalProfile() {
|
||||
SetCommand(0x3302);
|
||||
}
|
||||
|
||||
// index 0-3
|
||||
public MsgSetSingleBasalProfile(double[] values) {
|
||||
this();
|
||||
for (Integer i = 0; i < 24; i++) {
|
||||
AddParamInt((int) (values[i] * 100));
|
||||
}
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Set basal profile");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
int result = intFromBuff(bytes, 0, 1);
|
||||
if (result != 1) {
|
||||
failed = true;
|
||||
log.debug("Set basal profile result: " + result + " FAILED!!!");
|
||||
Notification reportFail = new Notification(Notification.PROFILE_SET_FAILED, MainApp.sResources.getString(R.string.profile_set_failed), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(reportFail));
|
||||
} else {
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Set basal profile result: " + result);
|
||||
Notification reportOK = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60);
|
||||
MainApp.bus().post(new EventNewNotification(reportOK));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
|
||||
/**
|
||||
* Created by mike on 09.12.2016.
|
||||
*/
|
||||
|
||||
public class MsgSetTime extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSetTime.class);
|
||||
|
||||
public MsgSetTime(Date time) {
|
||||
SetCommand(0x330a);
|
||||
AddParamDateTime(time);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
int result = intFromBuff(bytes, 0, 1);
|
||||
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Result: " + result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package info.nightscout.androidaps.plugins.DanaR.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 13.12.2016.
|
||||
*/
|
||||
|
||||
public class MsgSettingMeal extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingMeal.class);
|
||||
|
||||
public MsgSettingMeal() {
|
||||
SetCommand(0x3203);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
pump.basalStep = intFromBuff(bytes, 0, 1) / 100d;
|
||||
pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d;
|
||||
boolean bolusEnabled = intFromBuff(bytes, 2, 1) == 1;
|
||||
int melodyTime = intFromBuff(bytes, 3, 1);
|
||||
int blockTime = intFromBuff(bytes, 4, 1);
|
||||
pump.isConfigUD = intFromBuff(bytes, 5, 1) == 1;
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Basal step: " + pump.basalStep);
|
||||
log.debug("Bolus step: " + pump.bolusStep);
|
||||
log.debug("Bolus enabled: " + bolusEnabled);
|
||||
log.debug("Melody time: " + melodyTime);
|
||||
log.debug("Block time: " + blockTime);
|
||||
log.debug("Is Config U/d: " + pump.isConfigUD);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@ import java.util.Date;
|
|||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
|
@ -19,17 +20,18 @@ public class MsgSettingShippingInfo extends MessageBase {
|
|||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRPlugin.getDanaRPump().serialNumber = stringFromBuff(bytes, 0, 10);
|
||||
DanaRPlugin.getDanaRPump().shippingDate = dateFromBuff(bytes, 10);
|
||||
DanaRPlugin.getDanaRPump().shippingCountry = asciiStringFromBuff(bytes, 13, 3);
|
||||
if (DanaRPlugin.getDanaRPump().shippingDate.getTime() > new Date(116, 4, 1).getTime()) {
|
||||
DanaRPlugin.getDanaRPump().isNewPump = true;
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
pump.serialNumber = stringFromBuff(bytes, 0, 10);
|
||||
pump.shippingDate = dateFromBuff(bytes, 10);
|
||||
pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3);
|
||||
if (pump.shippingDate.getTime() > new Date(116, 4, 1).getTime()) {
|
||||
pump.isNewPump = true;
|
||||
} else
|
||||
DanaRPlugin.getDanaRPump().isNewPump = false;
|
||||
pump.isNewPump = false;
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Serial number: " + DanaRPlugin.getDanaRPump().serialNumber);
|
||||
log.debug("Shipping date: " + DanaRPlugin.getDanaRPump().shippingDate);
|
||||
log.debug("Shipping country: " + DanaRPlugin.getDanaRPump().shippingCountry);
|
||||
log.debug("Serial number: " + pump.serialNumber);
|
||||
log.debug("Shipping date: " + pump.shippingDate);
|
||||
log.debug("Shipping country: " + pump.shippingCountry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
|
||||
|
||||
public class MsgStatusBasic extends MessageBase {
|
||||
|
@ -15,41 +16,31 @@ public class MsgStatusBasic extends MessageBase {
|
|||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
boolean pumpSuspended = intFromBuff(bytes, 0, 1) == 1;
|
||||
boolean calculatorEnabled = intFromBuff(bytes, 1, 1) == 1;
|
||||
double dailyTotalUnits = intFromBuff(bytes, 2, 3) / 750d;
|
||||
int maxDailyTotalUnits = intFromBuff(bytes, 5, 2) / 100;
|
||||
double reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750d;
|
||||
boolean bolusBlocked = intFromBuff(bytes, 10, 1) == 1;
|
||||
double currentBasal = intFromBuff(bytes, 11, 2) / 100d;
|
||||
int tempBasalPercent = intFromBuff(bytes, 13, 1);
|
||||
boolean isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1;
|
||||
boolean isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1;
|
||||
int batteryRemaining = intFromBuff(bytes, 20, 1);
|
||||
DanaRPump pump = DanaRPlugin.getDanaRPump();
|
||||
|
||||
DanaRPlugin.getDanaRPump().pumpSuspended = pumpSuspended;
|
||||
DanaRPlugin.getDanaRPump().calculatorEnabled = calculatorEnabled;
|
||||
DanaRPlugin.getDanaRPump().dailyTotalUnits = dailyTotalUnits;
|
||||
DanaRPlugin.getDanaRPump().maxDailyTotalUnits = maxDailyTotalUnits;
|
||||
DanaRPlugin.getDanaRPump().reservoirRemainingUnits = reservoirRemainingUnits;
|
||||
DanaRPlugin.getDanaRPump().bolusBlocked = bolusBlocked;
|
||||
DanaRPlugin.getDanaRPump().currentBasal = currentBasal;
|
||||
DanaRPlugin.getDanaRPump().tempBasalPercent = tempBasalPercent;
|
||||
DanaRPlugin.getDanaRPump().isExtendedInProgress = isExtendedInProgress;
|
||||
DanaRPlugin.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress;
|
||||
DanaRPlugin.getDanaRPump().batteryRemaining = batteryRemaining;
|
||||
pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1;
|
||||
pump.calculatorEnabled = intFromBuff(bytes, 1, 1) == 1;
|
||||
pump.dailyTotalUnits = intFromBuff(bytes, 2, 3) / 750d;
|
||||
pump.maxDailyTotalUnits = intFromBuff(bytes, 5, 2) / 100;
|
||||
pump.reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750d;
|
||||
pump.bolusBlocked = intFromBuff(bytes, 10, 1) == 1;
|
||||
pump.currentBasal = intFromBuff(bytes, 11, 2) / 100d;
|
||||
pump.tempBasalPercent = intFromBuff(bytes, 13, 1);
|
||||
pump.isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1;
|
||||
pump.isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1;
|
||||
pump.batteryRemaining = intFromBuff(bytes, 20, 1);
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump suspended: " + pumpSuspended);
|
||||
log.debug("Calculator enabled: " + calculatorEnabled);
|
||||
log.debug("Daily total units: " + dailyTotalUnits);
|
||||
log.debug("Max daily total units: " + maxDailyTotalUnits);
|
||||
log.debug("Reservoir remaining units: " + reservoirRemainingUnits);
|
||||
log.debug("Bolus blocked: " + bolusBlocked);
|
||||
log.debug("Current basal: " + currentBasal);
|
||||
log.debug("Current temp basal percent: " + tempBasalPercent);
|
||||
log.debug("Is extended bolus running: " + isExtendedInProgress);
|
||||
log.debug("Is temp basal running: " + isTempBasalInProgress);
|
||||
log.debug("Pump suspended: " + pump.pumpSuspended);
|
||||
log.debug("Calculator enabled: " + pump.calculatorEnabled);
|
||||
log.debug("Daily total units: " + pump.dailyTotalUnits);
|
||||
log.debug("Max daily total units: " + pump.maxDailyTotalUnits);
|
||||
log.debug("Reservoir remaining units: " + pump.reservoirRemainingUnits);
|
||||
log.debug("Bolus blocked: " + pump.bolusBlocked);
|
||||
log.debug("Current basal: " + pump.currentBasal);
|
||||
log.debug("Current temp basal percent: " + pump.tempBasalPercent);
|
||||
log.debug("Is extended bolus running: " + pump.isExtendedInProgress);
|
||||
log.debug("Is temp basal running: " + pump.isTempBasalInProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.Dialogs.ProfileViewDialog;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.History.DanaRHistoryActivity;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SetWarnColor;
|
||||
|
||||
public class DanaRKoreanFragment extends Fragment implements FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRKoreanFragment.class);
|
||||
|
||||
private static DanaRKoreanPlugin danaRKoreanPlugin = new DanaRKoreanPlugin();
|
||||
|
||||
public static DanaRKoreanPlugin getPlugin() {
|
||||
return danaRKoreanPlugin;
|
||||
}
|
||||
|
||||
private static Handler sHandler;
|
||||
private static HandlerThread sHandlerThread;
|
||||
|
||||
private Handler loopHandler = new Handler();
|
||||
private Runnable refreshLoop = null;
|
||||
|
||||
TextView lastConnectionView;
|
||||
TextView btConnectionView;
|
||||
TextView lastBolusView;
|
||||
TextView dailyUnitsView;
|
||||
TextView basaBasalRateView;
|
||||
TextView tempBasalView;
|
||||
TextView extendedBolusView;
|
||||
TextView batteryView;
|
||||
TextView reservoirView;
|
||||
TextView iobView;
|
||||
Button viewProfileButton;
|
||||
Button historyButton;
|
||||
|
||||
public DanaRKoreanFragment() {
|
||||
if (sHandlerThread == null) {
|
||||
sHandlerThread = new HandlerThread(DanaRKoreanFragment.class.getSimpleName());
|
||||
sHandlerThread.start();
|
||||
sHandler = new Handler(sHandlerThread.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (refreshLoop == null) {
|
||||
refreshLoop = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateGUI();
|
||||
loopHandler.postDelayed(refreshLoop, 60 * 1000L);
|
||||
}
|
||||
};
|
||||
loopHandler.postDelayed(refreshLoop, 60 * 1000L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.danar_fragment, container, false);
|
||||
btConnectionView = (TextView) view.findViewById(R.id.danar_btconnection);
|
||||
lastConnectionView = (TextView) view.findViewById(R.id.danar_lastconnection);
|
||||
lastBolusView = (TextView) view.findViewById(R.id.danar_lastbolus);
|
||||
dailyUnitsView = (TextView) view.findViewById(R.id.danar_dailyunits);
|
||||
basaBasalRateView = (TextView) view.findViewById(R.id.danar_basabasalrate);
|
||||
tempBasalView = (TextView) view.findViewById(R.id.danar_tempbasal);
|
||||
extendedBolusView = (TextView) view.findViewById(R.id.danar_extendedbolus);
|
||||
batteryView = (TextView) view.findViewById(R.id.danar_battery);
|
||||
reservoirView = (TextView) view.findViewById(R.id.danar_reservoir);
|
||||
iobView = (TextView) view.findViewById(R.id.danar_iob);
|
||||
viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile);
|
||||
historyButton = (Button) view.findViewById(R.id.danar_history);
|
||||
|
||||
viewProfileButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
FragmentManager manager = getFragmentManager();
|
||||
ProfileViewDialog profileViewDialog = new ProfileViewDialog();
|
||||
profileViewDialog.show(manager, "ProfileViewDialog");
|
||||
}
|
||||
});
|
||||
|
||||
historyButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(getContext(), DanaRHistoryActivity.class));
|
||||
}
|
||||
});
|
||||
|
||||
btConnectionView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DanaRKoreanPlugin.sExecutionService.connect("Connect request from GUI");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
updateGUI();
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MainApp.bus().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDanaRConnectionStatus c) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (c.sStatus == EventDanaRConnectionStatus.CONNECTING)
|
||||
btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s");
|
||||
else if (c.sStatus == EventDanaRConnectionStatus.CONNECTED)
|
||||
btConnectionView.setText("{fa-bluetooth}");
|
||||
else
|
||||
btConnectionView.setText("{fa-bluetooth-b}");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDanaRNewStatus s) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventTempBasalChange s) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventPreferenceChange s) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
// GUI functions
|
||||
private void updateGUI() {
|
||||
final DateFormat formatTime = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||
|
||||
Activity activity = getActivity();
|
||||
if (activity != null && basaBasalRateView != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (DanaRKoreanPlugin.getDanaRPump().lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - DanaRKoreanPlugin.getDanaRPump().lastConnection.getTime();
|
||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||
lastConnectionView.setText(formatTime.format(DanaRKoreanPlugin.getDanaRPump().lastConnection) + " (" + agoMin + " " + MainApp.sResources.getString(R.string.minago) + ")");
|
||||
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
|
||||
}
|
||||
// if (DanaRKoreanPlugin.getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||
// Long agoMsec = new Date().getTime() - DanaRKoreanPlugin.getDanaRPump().lastBolusTime.getTime();
|
||||
// double agoHours = agoMsec / 60d / 60d / 1000d;
|
||||
// if (agoHours < 6) // max 6h back
|
||||
// lastBolusView.setText(formatTime.format(DanaRKoreanPlugin.getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(danaRKoreanPlugin.getDanaRPump().lastBolusAmount) + " U");
|
||||
// else lastBolusView.setText("");
|
||||
// }
|
||||
|
||||
dailyUnitsView.setText(DecimalFormatter.to0Decimal(DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits) + " / " + DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits + " U");
|
||||
SetWarnColor.setColor(dailyUnitsView, DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits, DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits * 0.75d, DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits * 0.9d);
|
||||
basaBasalRateView.setText("( " + (DanaRKoreanPlugin.getDanaRPump().activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(danaRKoreanPlugin.getBaseBasalRate()) + " U/h");
|
||||
if (danaRKoreanPlugin.isRealTempBasalInProgress()) {
|
||||
tempBasalView.setText(danaRKoreanPlugin.getRealTempBasal().toString());
|
||||
} else {
|
||||
tempBasalView.setText("");
|
||||
}
|
||||
if (danaRKoreanPlugin.isExtendedBoluslInProgress()) {
|
||||
extendedBolusView.setText(danaRKoreanPlugin.getExtendedBolus().toString());
|
||||
} else {
|
||||
extendedBolusView.setText("");
|
||||
}
|
||||
reservoirView.setText(DecimalFormatter.to0Decimal(DanaRKoreanPlugin.getDanaRPump().reservoirRemainingUnits) + " / 300 U");
|
||||
SetWarnColor.setColorInverse(reservoirView, DanaRKoreanPlugin.getDanaRPump().reservoirRemainingUnits, 50d, 20d);
|
||||
batteryView.setText("{fa-battery-" + (DanaRKoreanPlugin.getDanaRPump().batteryRemaining / 25) + "}");
|
||||
SetWarnColor.setColorInverse(batteryView, DanaRKoreanPlugin.getDanaRPump().batteryRemaining, 51d, 26d);
|
||||
iobView.setText(DanaRKoreanPlugin.getDanaRPump().iob + " U");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,826 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class DanaRKoreanPlugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRKoreanPlugin.class);
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return DanaRKoreanFragment.class.getName();
|
||||
}
|
||||
|
||||
static boolean fragmentPumpEnabled = true;
|
||||
static boolean fragmentProfileEnabled = true;
|
||||
static boolean fragmentPumpVisible = true;
|
||||
|
||||
public static ExecutionService sExecutionService;
|
||||
|
||||
|
||||
private static DanaRKoreanPump sDanaRKoreanPump = new DanaRKoreanPump();
|
||||
private static boolean useExtendedBoluses = false;
|
||||
|
||||
private PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
public static DanaRKoreanPump getDanaRPump() {
|
||||
return sDanaRKoreanPump;
|
||||
}
|
||||
|
||||
public DanaRKoreanPlugin() {
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false);
|
||||
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Intent intent = new Intent(context, ExecutionService.class);
|
||||
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
MainApp.bus().register(this);
|
||||
|
||||
pumpDescription.isBolusCapable = true; // TODO: use description in setTempBasalAbsolute
|
||||
pumpDescription.bolusStep = 0.1d;
|
||||
|
||||
pumpDescription.isExtendedBolusCapable = true;
|
||||
pumpDescription.extendedBolusStep = 0.1d;
|
||||
|
||||
pumpDescription.isTempBasalCapable = true;
|
||||
pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT;
|
||||
pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT;
|
||||
pumpDescription.maxHighTempPercent = 200;
|
||||
pumpDescription.maxHighTempAbsolute = 0;
|
||||
pumpDescription.lowTempPercentStep = 10;
|
||||
pumpDescription.lowTempAbsoluteStep = 0;
|
||||
pumpDescription.lowTempPercentDuration = 60;
|
||||
pumpDescription.lowTempAbsoluteDuration = 60;
|
||||
pumpDescription.highTempPercentStep = 10;
|
||||
pumpDescription.highTempAbsoluteStep = 0.05d;
|
||||
pumpDescription.highTempPercentDuration = 60;
|
||||
pumpDescription.highTempAbsoluteDuration = 30;
|
||||
|
||||
pumpDescription.isSetBasalProfileCapable = true;
|
||||
pumpDescription.basalStep = 0.01d;
|
||||
pumpDescription.basalMinimumRate = 0.1d;
|
||||
|
||||
pumpDescription.isRefillingCapable = true;
|
||||
}
|
||||
|
||||
ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
log.debug("Service is disconnected");
|
||||
sExecutionService = null;
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
log.debug("Service is connected");
|
||||
ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service;
|
||||
sExecutionService = mLocalBinder.getServiceInstance();
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventAppExit e) {
|
||||
MainApp.instance().getApplicationContext().unbindService(mConnection);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventPreferenceChange s) {
|
||||
if (isEnabled(PUMP)) {
|
||||
boolean previousValue = useExtendedBoluses;
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false);
|
||||
|
||||
pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT;
|
||||
|
||||
if (useExtendedBoluses != previousValue && isExtendedBoluslInProgress()) {
|
||||
sExecutionService.extendedBolusStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin base interface
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.PUMP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.danarkoreanpump);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
||||
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
|
||||
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
||||
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == PluginBase.PROFILE)
|
||||
this.fragmentProfileEnabled = fragmentEnabled;
|
||||
else if (type == PluginBase.PUMP)
|
||||
this.fragmentPumpEnabled = fragmentEnabled;
|
||||
// if pump profile was enabled need to switch to another too
|
||||
if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) {
|
||||
setFragmentEnabled(PluginBase.PROFILE, false);
|
||||
setFragmentVisible(PluginBase.PROFILE, false);
|
||||
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(PluginBase.PROFILE, true);
|
||||
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentVisible(PluginBase.PROFILE, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == PluginBase.PUMP)
|
||||
this.fragmentPumpVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return getDanaRPump().lastConnection.getTime() > 0 && !getDanaRPump().isConfigUD && !getDanaRPump().isEasyModeEnabled && getDanaRPump().isExtendedBolusEnabled;
|
||||
}
|
||||
|
||||
// Pump interface
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
if (getRealTempBasal() != null) return true;
|
||||
if (getExtendedBolus() != null && useExtendedBoluses) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isRealTempBasalInProgress() {
|
||||
return getRealTempBasal() != null; //TODO: crosscheck here
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExtendedBoluslInProgress() {
|
||||
return getExtendedBolus() != null; //TODO: crosscheck here
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setNewBasalProfile(NSProfile profile) {
|
||||
if (sExecutionService == null) {
|
||||
log.error("setNewBasalProfile sExecutionService is null");
|
||||
return FAILED;
|
||||
}
|
||||
if (!isInitialized()) {
|
||||
log.error("setNewBasalProfile not initialized");
|
||||
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
return FAILED;
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||
}
|
||||
if (!sExecutionService.updateBasalsInPump(profile)) {
|
||||
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
return FAILED;
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThisProfileSet(NSProfile profile) {
|
||||
if (!isInitialized())
|
||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||
DanaRKoreanPump pump = getDanaRPump();
|
||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
||||
Double profileValue = profile.getBasal(h * basalIncrement);
|
||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return getDanaRPump().currentBasal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTempBasalAbsoluteRate() {
|
||||
if (isRealTempBasalInProgress()) {
|
||||
if (getRealTempBasal().isAbsolute) {
|
||||
return getRealTempBasal().absolute;
|
||||
} else {
|
||||
Double baseRate = getBaseBasalRate();
|
||||
Double tempRate = baseRate * (getRealTempBasal().percent / 100d);
|
||||
return tempRate;
|
||||
}
|
||||
}
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||
return getBaseBasalRate() + getExtendedBolus().absolute;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTempBasalRemainingMinutes() {
|
||||
if (isRealTempBasalInProgress())
|
||||
return getRealTempBasal().getPlannedRemainingMinutes();
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses)
|
||||
return getExtendedBolus().getPlannedRemainingMinutes();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getTempBasal() {
|
||||
if (isRealTempBasalInProgress())
|
||||
return getRealTempBasal();
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses)
|
||||
return getExtendedBolus();
|
||||
return null;
|
||||
}
|
||||
|
||||
public TempBasal getTempBasal(Date time) {
|
||||
TempBasal temp = MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(time);
|
||||
if (temp != null) return temp;
|
||||
if (useExtendedBoluses)
|
||||
return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(time);
|
||||
return null;
|
||||
}
|
||||
|
||||
public TempBasal getRealTempBasal() {
|
||||
return MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getExtendedBolus() {
|
||||
return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) {
|
||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
||||
if (insulin > 0 || carbs > 0) {
|
||||
Treatment t = new Treatment();
|
||||
boolean connectionOK = false;
|
||||
if (insulin > 0 || carbs > 0) connectionOK = sExecutionService.bolus(insulin, carbs, t);
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = connectionOK;
|
||||
result.bolusDelivered = t.insulin;
|
||||
result.carbsDelivered = carbs;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
if (Config.logPumpActions)
|
||||
log.debug("deliverTreatment: OK. Asked: " + insulin + " Delivered: " + result.bolusDelivered);
|
||||
return result;
|
||||
} else {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.bolusDelivered = 0d;
|
||||
result.carbsDelivered = 0;
|
||||
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
||||
log.error("deliverTreatment: Invalid input");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopBolusDelivering() {
|
||||
if (sExecutionService == null) {
|
||||
log.error("stopBolusDelivering sExecutionService is null");
|
||||
return;
|
||||
}
|
||||
sExecutionService.bolusStop();
|
||||
}
|
||||
|
||||
// This is called from APS
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) {
|
||||
// Recheck pump status if older than 30 min
|
||||
if (getDanaRPump().lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) {
|
||||
doConnect("setTempBasalAbsolute old data");
|
||||
}
|
||||
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
|
||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||
absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate);
|
||||
|
||||
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
|
||||
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
|
||||
final boolean doHighTemp = absoluteRate > getBaseBasalRate() && !useExtendedBoluses;
|
||||
final boolean doExtendedTemp = absoluteRate > getBaseBasalRate() && useExtendedBoluses;
|
||||
|
||||
if (doTempOff) {
|
||||
// If extended in progress
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Stopping extended bolus (doTempOff)");
|
||||
return cancelExtendedBolus();
|
||||
}
|
||||
// If temp in progress
|
||||
if (isRealTempBasalInProgress()) {
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Stopping temp basal (doTempOff)");
|
||||
return cancelRealTempBasal();
|
||||
}
|
||||
result.success = true;
|
||||
result.enacted = false;
|
||||
result.percent = 100;
|
||||
result.isPercent = true;
|
||||
result.isTempCancel = true;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: doTempOff OK");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (doLowTemp || doHighTemp) {
|
||||
Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
|
||||
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue();
|
||||
else percentRate = Round.floorTo((double) percentRate, 10d).intValue();
|
||||
if (percentRate > 200) {
|
||||
percentRate = 200;
|
||||
}
|
||||
// If extended in progress
|
||||
if (isExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)");
|
||||
result = cancelExtendedBolus();
|
||||
if (!result.success) {
|
||||
log.error("setTempBasalAbsolute: Failed to stop previous extended bolus (doLowTemp || doHighTemp)");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Check if some temp is already in progress
|
||||
if (isRealTempBasalInProgress()) {
|
||||
// Correct basal already set ?
|
||||
if (getRealTempBasal().percent == percentRate) {
|
||||
result.success = true;
|
||||
result.percent = percentRate;
|
||||
result.absolute = getTempBasalAbsoluteRate();
|
||||
result.enacted = false;
|
||||
result.duration = ((Double) getTempBasalRemainingMinutes()).intValue();
|
||||
result.isPercent = true;
|
||||
result.isTempCancel = false;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)");
|
||||
return result;
|
||||
} else {
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Stopping temp basal (doLowTemp || doHighTemp)");
|
||||
result = cancelRealTempBasal();
|
||||
// Check for proper result
|
||||
if (!result.success) {
|
||||
log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doLowTemp || doHighTemp)");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert duration from minutes to hours
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
|
||||
return setTempBasalPercent(percentRate, durationInMinutes);
|
||||
}
|
||||
if (doExtendedTemp) {
|
||||
// Check if some temp is already in progress
|
||||
if (isRealTempBasalInProgress()) {
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)");
|
||||
result = cancelRealTempBasal();
|
||||
// Check for proper result
|
||||
if (!result.success) {
|
||||
log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doExtendedTemp)");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate # of halfHours from minutes
|
||||
Integer durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
||||
// We keep current basal running so need to sub current basal
|
||||
Double extendedRateToSet = absoluteRate - getBaseBasalRate();
|
||||
extendedRateToSet = configBuilderPlugin.applyBasalConstraints(extendedRateToSet);
|
||||
// needs to be rounded to 0.1
|
||||
extendedRateToSet = Round.roundTo(extendedRateToSet, 0.1d);
|
||||
|
||||
// What is current rate of extended bolusing in u/h?
|
||||
if (Config.logPumpActions) {
|
||||
log.debug("setTempBasalAbsolute: Extended bolus in progress: " + isExtendedBoluslInProgress() + " rate: " + getDanaRPump().extendedBolusAbsoluteRate + "U/h duration remaining: " + getDanaRPump().extendedBolusRemainingMinutes + "min");
|
||||
log.debug("setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h");
|
||||
}
|
||||
|
||||
// Compare with extended rate in progress
|
||||
if (Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < 0.02D) { // Allow some rounding diff
|
||||
// correct extended already set
|
||||
result.success = true;
|
||||
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||
result.enacted = false;
|
||||
result.duration = getDanaRPump().extendedBolusRemainingMinutes;
|
||||
result.isPercent = false;
|
||||
result.isTempCancel = false;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Correct extended already set");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Now set new extended, no need to to stop previous (if running) because it's replaced
|
||||
Double extendedAmount = extendedRateToSet / 2 * durationInHalfHours;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Setting extended: " + extendedAmount + "U halfhours: " + durationInHalfHours);
|
||||
result = setExtendedBolus(extendedAmount, durationInMinutes);
|
||||
if (!result.success) {
|
||||
log.error("setTempBasalAbsolute: Failed to set extended bolus");
|
||||
return result;
|
||||
}
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalAbsolute: Extended bolus set ok");
|
||||
result.absolute = result.absolute + getBaseBasalRate();
|
||||
return result;
|
||||
}
|
||||
// We should never end here
|
||||
log.error("setTempBasalAbsolute: Internal error");
|
||||
result.success = false;
|
||||
result.comment = "Internal error";
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||
percent = configBuilderPlugin.applyBasalConstraints(percent);
|
||||
if (percent < 0) {
|
||||
result.isTempCancel = false;
|
||||
result.enacted = false;
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
||||
log.error("setTempBasalPercent: Invalid input");
|
||||
return result;
|
||||
}
|
||||
if (percent > 200) percent = 200;
|
||||
if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) {
|
||||
result.enacted = false;
|
||||
result.success = true;
|
||||
result.isTempCancel = false;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
result.duration = getDanaRPump().tempBasalRemainingMin;
|
||||
result.percent = getDanaRPump().tempBasalPercent;
|
||||
result.isPercent = true;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalPercent: Correct value already set");
|
||||
return result;
|
||||
}
|
||||
int durationInHours = Math.max(durationInMinutes / 60, 1);
|
||||
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
|
||||
if (connectionOK && getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) {
|
||||
result.enacted = true;
|
||||
result.success = true;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
result.isTempCancel = false;
|
||||
result.duration = getDanaRPump().tempBasalRemainingMin;
|
||||
result.percent = getDanaRPump().tempBasalPercent;
|
||||
result.isPercent = true;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setTempBasalPercent: OK");
|
||||
return result;
|
||||
}
|
||||
result.enacted = false;
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||
log.error("setTempBasalPercent: Failed to set temp basal");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
||||
// needs to be rounded to 0.1
|
||||
insulin = Round.roundTo(insulin, 0.1d);
|
||||
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
if (getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < 0.1d) {
|
||||
result.enacted = false;
|
||||
result.success = true;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
result.duration = getDanaRPump().extendedBolusRemainingMinutes;
|
||||
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||
result.isPercent = false;
|
||||
result.isTempCancel = false;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setExtendedBolus: Correct extended bolus already set");
|
||||
return result;
|
||||
}
|
||||
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
||||
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
|
||||
if (connectionOK && getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < 0.1d) {
|
||||
result.enacted = true;
|
||||
result.success = true;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
result.isTempCancel = false;
|
||||
result.duration = getDanaRPump().extendedBolusRemainingMinutes;
|
||||
result.absolute = getDanaRPump().extendedBolusAbsoluteRate;
|
||||
result.bolusDelivered = getDanaRPump().extendedBolusAmount;
|
||||
result.isPercent = false;
|
||||
if (Config.logPumpActions)
|
||||
log.debug("setExtendedBolus: OK");
|
||||
return result;
|
||||
}
|
||||
result.enacted = false;
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||
log.error("setExtendedBolus: Failed to extended bolus");
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelTempBasal() {
|
||||
if (isRealTempBasalInProgress())
|
||||
return cancelRealTempBasal();
|
||||
if (isExtendedBoluslInProgress())
|
||||
return cancelExtendedBolus();
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = true;
|
||||
result.enacted = false;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
result.isTempCancel = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public PumpEnactResult cancelRealTempBasal() {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
if (getDanaRPump().isTempBasalInProgress) {
|
||||
sExecutionService.tempBasalStop();
|
||||
result.enacted = true;
|
||||
result.isTempCancel = true;
|
||||
}
|
||||
if (!getDanaRPump().isTempBasalInProgress) {
|
||||
result.success = true;
|
||||
result.isTempCancel = true;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
if (Config.logPumpActions)
|
||||
log.debug("cancelRealTempBasal: OK");
|
||||
return result;
|
||||
} else {
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||
result.isTempCancel = true;
|
||||
log.error("cancelRealTempBasal: Failed to cancel temp basal");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelExtendedBolus() {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
if (getDanaRPump().isExtendedInProgress) {
|
||||
sExecutionService.extendedBolusStop();
|
||||
result.enacted = true;
|
||||
result.isTempCancel = true;
|
||||
}
|
||||
if (!getDanaRPump().isExtendedInProgress) {
|
||||
result.success = true;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
if (Config.logPumpActions)
|
||||
log.debug("cancelExtendedBolus: OK");
|
||||
return result;
|
||||
} else {
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static void doConnect(String from) {
|
||||
if (sExecutionService != null) sExecutionService.connect(from);
|
||||
}
|
||||
|
||||
public static boolean isConnected() {
|
||||
return sExecutionService != null && sExecutionService.isConnected();
|
||||
}
|
||||
|
||||
public static boolean isConnecting() {
|
||||
return sExecutionService != null && sExecutionService.isConnecting();
|
||||
}
|
||||
|
||||
public static void doDisconnect(String from) {
|
||||
if (sExecutionService != null) sExecutionService.disconnect(from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getJSONStatus() {
|
||||
if (getDanaRPump().lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) {
|
||||
return null;
|
||||
}
|
||||
JSONObject pump = new JSONObject();
|
||||
JSONObject battery = new JSONObject();
|
||||
JSONObject status = new JSONObject();
|
||||
JSONObject extended = new JSONObject();
|
||||
try {
|
||||
battery.put("percent", getDanaRPump().batteryRemaining);
|
||||
status.put("status", "normal");
|
||||
status.put("timestamp", DateUtil.toISOString(getDanaRPump().lastConnection));
|
||||
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
||||
extended.put("PumpIOB", getDanaRPump().iob);
|
||||
// extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString());
|
||||
// extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount);
|
||||
if (isTempBasalInProgress()) {
|
||||
extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate());
|
||||
extended.put("TempBasalStart", getTempBasal().timeStart.toLocaleString());
|
||||
extended.put("TempBasalRemaining", getTempBasal().getPlannedRemainingMinutes());
|
||||
extended.put("IsExtended", getTempBasal().isExtended);
|
||||
}
|
||||
extended.put("BaseBasalRate", getBaseBasalRate());
|
||||
try {
|
||||
extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
pump.put("battery", battery);
|
||||
pump.put("status", status);
|
||||
pump.put("extended", extended);
|
||||
pump.put("reservoir", (int) getDanaRPump().reservoirRemainingUnits);
|
||||
pump.put("clock", DateUtil.toISOString(new Date()));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return pump;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceID() {
|
||||
return getDanaRPump().serialNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpDescription getPumpDescription() {
|
||||
return pumpDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraint interface
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean isLoopEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosedModeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutosensModeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAMAModeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PointlessBooleanExpression")
|
||||
@Override
|
||||
public Double applyBasalConstraints(Double absoluteRate) {
|
||||
double origAbsoluteRate = absoluteRate;
|
||||
if (getDanaRPump() != null) {
|
||||
if (absoluteRate > getDanaRPump().maxBasal) {
|
||||
absoluteRate = getDanaRPump().maxBasal;
|
||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
||||
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
|
||||
}
|
||||
}
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PointlessBooleanExpression")
|
||||
@Override
|
||||
public Integer applyBasalConstraints(Integer percentRate) {
|
||||
Integer origPercentRate = percentRate;
|
||||
if (percentRate < 0) percentRate = 0;
|
||||
if (percentRate > 200) percentRate = 200;
|
||||
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
@SuppressWarnings("PointlessBooleanExpression")
|
||||
@Override
|
||||
public Double applyBolusConstraints(Double insulin) {
|
||||
double origInsulin = insulin;
|
||||
if (getDanaRPump() != null) {
|
||||
if (insulin > getDanaRPump().maxBolus) {
|
||||
insulin = getDanaRPump().maxBolus;
|
||||
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
|
||||
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
|
||||
}
|
||||
}
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer applyCarbsConstraints(Integer carbs) {
|
||||
return carbs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public NSProfile getProfile() {
|
||||
DanaRKoreanPump pump = getDanaRPump();
|
||||
if (pump.lastSettingsRead.getTime() == 0)
|
||||
return null; // no info now
|
||||
return pump.createConvertedProfile();
|
||||
}
|
||||
|
||||
// Reply for sms communicator
|
||||
public String shortStatus() {
|
||||
String ret = "";
|
||||
if (getDanaRPump().lastConnection.getTime() != 0) {
|
||||
Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime();
|
||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||
ret += "LastConn: " + agoMin + " minago\n";
|
||||
}
|
||||
// if (getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||
// ret += "LastBolus: " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", getDanaRPump().lastBolusTime) + "\n";
|
||||
// }
|
||||
if (isRealTempBasalInProgress()) {
|
||||
ret += "Temp: " + getRealTempBasal().toString() + "\n";
|
||||
}
|
||||
if (isExtendedBoluslInProgress()) {
|
||||
ret += "Extended: " + getExtendedBolus().toString() + "\n";
|
||||
}
|
||||
ret += "IOB: " + getDanaRPump().iob + "U\n";
|
||||
ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n";
|
||||
ret += "Batt: " + getDanaRPump().batteryRemaining + "\n";
|
||||
return ret;
|
||||
}
|
||||
// TODO: daily total constraint
|
||||
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
/**
|
||||
* Created by mike on 04.07.2016.
|
||||
*/
|
||||
public class DanaRKoreanPump {
|
||||
public static final int UNITS_MGDL = 0;
|
||||
public static final int UNITS_MMOL = 1;
|
||||
|
||||
public static final int DELIVERY_PRIME = 0x01;
|
||||
public static final int DELIVERY_STEP_BOLUS = 0x02;
|
||||
public static final int DELIVERY_BASAL = 0x04;
|
||||
public static final int DELIVERY_EXT_BOLUS = 0x08;
|
||||
|
||||
public static final String PROFILE_PREFIX = "DanaR-";
|
||||
|
||||
public Date lastConnection = new Date(0);
|
||||
public Date lastSettingsRead = new Date(0);
|
||||
|
||||
// Info
|
||||
public String serialNumber = "";
|
||||
public Date shippingDate = new Date(0);
|
||||
public String shippingCountry = "";
|
||||
public boolean isNewPump = false;
|
||||
public int password = -1;
|
||||
public Date pumpTime = new Date(0);
|
||||
|
||||
public static final int DOMESTIC_MODEL = 0x01;
|
||||
public static final int EXPORT_MODEL = 0x03;
|
||||
public int model;
|
||||
public int protocol;
|
||||
public int productCode;
|
||||
|
||||
public boolean isConfigUD;
|
||||
public boolean isExtendedBolusEnabled;
|
||||
public boolean isEasyModeEnabled;
|
||||
|
||||
// Status
|
||||
public double dailyTotalUnits;
|
||||
public int maxDailyTotalUnits;
|
||||
|
||||
public double bolusStep;
|
||||
public double basalStep;
|
||||
|
||||
public double iob;
|
||||
|
||||
public double reservoirRemainingUnits;
|
||||
public int batteryRemaining;
|
||||
|
||||
public double currentBasal;
|
||||
|
||||
public boolean isTempBasalInProgress;
|
||||
public int tempBasalPercent;
|
||||
public int tempBasalRemainingMin;
|
||||
public int tempBasalTotalSec;
|
||||
public Date tempBasalStart;
|
||||
|
||||
public boolean isExtendedInProgress;
|
||||
public int extendedBolusMinutes;
|
||||
public double extendedBolusAmount;
|
||||
public double extendedBolusAbsoluteRate;
|
||||
public int extendedBolusSoFarInMinutes;
|
||||
public Date extendedBolusStart;
|
||||
public int extendedBolusRemainingMinutes;
|
||||
|
||||
// Profile
|
||||
public int units;
|
||||
public int easyBasalMode;
|
||||
public boolean basal48Enable = false;
|
||||
public int currentCIR;
|
||||
public double currentCF;
|
||||
public double currentAI;
|
||||
public double currentTarget;
|
||||
public int currentAIDR;
|
||||
|
||||
public int morningCIR;
|
||||
public double morningCF;
|
||||
public int afternoonCIR;
|
||||
public double afternoonCF;
|
||||
public int eveningCIR;
|
||||
public double eveningCF;
|
||||
public int nightCIR;
|
||||
public double nightCF;
|
||||
|
||||
|
||||
public int activeProfile = 0;
|
||||
public double[][] pumpProfiles = null;
|
||||
|
||||
//Limits
|
||||
public double maxBolus;
|
||||
public double maxBasal;
|
||||
|
||||
public NSProfile createConvertedProfile() {
|
||||
JSONObject json = new JSONObject();
|
||||
JSONObject store = new JSONObject();
|
||||
JSONObject profile = new JSONObject();
|
||||
|
||||
// Morning / 6:00–10:59
|
||||
// Afternoon / 11:00–16:59
|
||||
// Evening / 17:00–21:59
|
||||
// Night / 22:00–5:59
|
||||
|
||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
double dia = SafeParse.stringToDouble(SP.getString("danarprofile_dia", "3"));
|
||||
double car = SafeParse.stringToDouble(SP.getString("danarprofile_car", "20"));
|
||||
|
||||
try {
|
||||
json.put("defaultProfile", PROFILE_PREFIX + (activeProfile + 1));
|
||||
json.put("store", store);
|
||||
profile.put("dia", dia);
|
||||
|
||||
JSONArray carbratios = new JSONArray();
|
||||
carbratios.put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", nightCIR));
|
||||
carbratios.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCIR));
|
||||
carbratios.put(new JSONObject().put("time", "11:00").put("timeAsSeconds", 11 * 3600).put("value", afternoonCIR));
|
||||
carbratios.put(new JSONObject().put("time", "14:00").put("timeAsSeconds", 17 * 3600).put("value", eveningCIR));
|
||||
carbratios.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCIR));
|
||||
profile.put("carbratio", carbratios);
|
||||
|
||||
profile.put("carbs_hr", car);
|
||||
|
||||
JSONArray sens = new JSONArray();
|
||||
sens.put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", nightCF));
|
||||
sens.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCF));
|
||||
sens.put(new JSONObject().put("time", "11:00").put("timeAsSeconds", 11 * 3600).put("value", afternoonCF));
|
||||
sens.put(new JSONObject().put("time", "17:00").put("timeAsSeconds", 17 * 3600).put("value", eveningCF));
|
||||
sens.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCF));
|
||||
profile.put("sens", sens);
|
||||
|
||||
JSONArray basals = new JSONArray();
|
||||
int basalValues = basal48Enable ? 48 : 24;
|
||||
int basalIncrement = basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
String time;
|
||||
DecimalFormat df = new DecimalFormat("00");
|
||||
if (basal48Enable) {
|
||||
time = df.format((long) h / 2) + ":" + df.format(30 * (h % 2));
|
||||
} else {
|
||||
time = df.format(h) + ":00";
|
||||
}
|
||||
basals.put(new JSONObject().put("time", time).put("timeAsSeconds", h * basalIncrement).put("value", pumpProfiles[activeProfile][h]));
|
||||
}
|
||||
profile.put("basal", basals);
|
||||
|
||||
profile.put("target_low", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", currentTarget)));
|
||||
profile.put("target_high", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", currentTarget)));
|
||||
profile.put("units", units == UNITS_MGDL ? Constants.MGDL : Constants.MMOL);
|
||||
store.put(PROFILE_PREFIX + (activeProfile + 1), profile);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return new NSProfile(json, PROFILE_PREFIX + (activeProfile + 1));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,460 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.History;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.stmt.PreparedQuery;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
import com.j256.ormlite.stmt.Where;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class DanaRHistoryActivity extends Activity {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class);
|
||||
|
||||
private boolean mBounded;
|
||||
private static ExecutionService mExecutionService;
|
||||
|
||||
private Handler mHandler;
|
||||
private static HandlerThread mHandlerThread;
|
||||
|
||||
static NSProfile profile = null;
|
||||
|
||||
Spinner historyTypeSpinner;
|
||||
TextView statusView;
|
||||
Button reloadButton;
|
||||
Button syncButton;
|
||||
RecyclerView recyclerView;
|
||||
LinearLayoutManager llm;
|
||||
|
||||
static byte showingType = RecordTypes.RECORD_TYPE_ALARM;
|
||||
List<DanaRHistoryRecord> historyList = new ArrayList<>();
|
||||
|
||||
public static class TypeList {
|
||||
public byte type;
|
||||
String name;
|
||||
|
||||
public TypeList(byte type, String name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public DanaRHistoryActivity() {
|
||||
super();
|
||||
mHandlerThread = new HandlerThread(DanaRHistoryActivity.class.getSimpleName());
|
||||
mHandlerThread.start();
|
||||
this.mHandler = new Handler(mHandlerThread.getLooper());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Intent intent = new Intent(this, ExecutionService.class);
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
MainApp.bus().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (mBounded) {
|
||||
unbindService(mConnection);
|
||||
mBounded = false;
|
||||
}
|
||||
}
|
||||
|
||||
ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
log.debug("Service is disconnected");
|
||||
mBounded = false;
|
||||
mExecutionService = null;
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
log.debug("Service is connected");
|
||||
mBounded = true;
|
||||
ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service;
|
||||
mExecutionService = mLocalBinder.getServiceInstance();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.danar_historyactivity);
|
||||
|
||||
historyTypeSpinner = (Spinner) findViewById(R.id.danar_historytype);
|
||||
statusView = (TextView) findViewById(R.id.danar_historystatus);
|
||||
reloadButton = (Button) findViewById(R.id.danar_historyreload);
|
||||
syncButton = (Button) findViewById(R.id.danar_historysync);
|
||||
recyclerView = (RecyclerView) findViewById(R.id.danar_history_recyclerview);
|
||||
|
||||
recyclerView.setHasFixedSize(true);
|
||||
llm = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(llm);
|
||||
|
||||
RecyclerViewAdapter adapter = new RecyclerViewAdapter(historyList);
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
statusView.setVisibility(View.GONE);
|
||||
|
||||
// Types
|
||||
|
||||
ArrayList<TypeList> typeList = new ArrayList<>();
|
||||
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ALARM, getString(R.string.danar_history_alarm)));
|
||||
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BASALHOUR, getString(R.string.danar_history_basalhours)));
|
||||
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BOLUS, getString(R.string.danar_history_bolus)));
|
||||
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_CARBO, getString(R.string.danar_history_carbohydrates)));
|
||||
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_DAILY, getString(R.string.danar_history_dailyinsulin)));
|
||||
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_GLUCOSE, getString(R.string.danar_history_glucose)));
|
||||
|
||||
ArrayAdapter<TypeList> spinnerAdapter = new ArrayAdapter<>(this,
|
||||
android.R.layout.simple_spinner_item, typeList);
|
||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
historyTypeSpinner.setAdapter(spinnerAdapter);
|
||||
|
||||
reloadButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mExecutionService.isConnected() || mExecutionService.isConnecting()) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy));
|
||||
return;
|
||||
}
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
syncButton.setVisibility(View.GONE);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
clearCardView();
|
||||
mExecutionService.loadHistory(selected.type);
|
||||
loadDataFromDB(selected.type);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.VISIBLE);
|
||||
syncButton.setVisibility(View.VISIBLE);
|
||||
statusView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
syncButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
syncButton.setVisibility(View.GONE);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
DanaRNSHistorySync sync = new DanaRNSHistorySync(historyList);
|
||||
sync.sync(DanaRNSHistorySync.SYNC_ALL);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.VISIBLE);
|
||||
syncButton.setVisibility(View.VISIBLE);
|
||||
statusView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem();
|
||||
loadDataFromDB(selected.type);
|
||||
showingType = selected.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
clearCardView();
|
||||
}
|
||||
});
|
||||
profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
if (profile == null) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile));
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
public static class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.HistoryViewHolder> {
|
||||
|
||||
List<DanaRHistoryRecord> historyList;
|
||||
|
||||
RecyclerViewAdapter(List<DanaRHistoryRecord> historyList) {
|
||||
this.historyList = historyList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
|
||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.danar_history_item, viewGroup, false);
|
||||
return new HistoryViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(HistoryViewHolder holder, int position) {
|
||||
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||
DanaRHistoryRecord record = historyList.get(position);
|
||||
holder.time.setText(df.format(new Date(record.getRecordDate())));
|
||||
holder.value.setText(DecimalFormatter.to2Decimal(record.getRecordValue()));
|
||||
holder.stringvalue.setText(record.getStringRecordValue());
|
||||
holder.bolustype.setText(record.getBolusType());
|
||||
holder.duration.setText(DecimalFormatter.to0Decimal(record.getRecordDuration()));
|
||||
holder.alarm.setText(record.getRecordAlarm());
|
||||
switch (showingType) {
|
||||
case RecordTypes.RECORD_TYPE_ALARM:
|
||||
holder.time.setVisibility(View.VISIBLE);
|
||||
holder.value.setVisibility(View.VISIBLE);
|
||||
holder.stringvalue.setVisibility(View.GONE);
|
||||
holder.bolustype.setVisibility(View.GONE);
|
||||
holder.duration.setVisibility(View.GONE);
|
||||
holder.dailybasal.setVisibility(View.GONE);
|
||||
holder.dailybolus.setVisibility(View.GONE);
|
||||
holder.dailytotal.setVisibility(View.GONE);
|
||||
holder.alarm.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||
holder.time.setVisibility(View.VISIBLE);
|
||||
holder.value.setVisibility(View.VISIBLE);
|
||||
holder.stringvalue.setVisibility(View.GONE);
|
||||
holder.bolustype.setVisibility(View.VISIBLE);
|
||||
holder.duration.setVisibility(View.VISIBLE);
|
||||
holder.dailybasal.setVisibility(View.GONE);
|
||||
holder.dailybolus.setVisibility(View.GONE);
|
||||
holder.dailytotal.setVisibility(View.GONE);
|
||||
holder.alarm.setVisibility(View.GONE);
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_DAILY:
|
||||
df = DateFormat.getDateInstance(DateFormat.SHORT);
|
||||
holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + "U");
|
||||
holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + "U");
|
||||
holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()+ record.getRecordDailyBasal()) + "U");
|
||||
holder.time.setText(df.format(new Date(record.getRecordDate())));
|
||||
holder.time.setVisibility(View.VISIBLE);
|
||||
holder.value.setVisibility(View.GONE);
|
||||
holder.stringvalue.setVisibility(View.GONE);
|
||||
holder.bolustype.setVisibility(View.GONE);
|
||||
holder.duration.setVisibility(View.GONE);
|
||||
holder.dailybasal.setVisibility(View.VISIBLE);
|
||||
holder.dailybolus.setVisibility(View.VISIBLE);
|
||||
holder.dailytotal.setVisibility(View.VISIBLE);
|
||||
holder.alarm.setVisibility(View.GONE);
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||
holder.value.setText(NSProfile.toUnitsString(record.getRecordValue(), record.getRecordValue() * Constants.MGDL_TO_MMOLL, profile.getUnits()));
|
||||
// rest is the same
|
||||
case RecordTypes.RECORD_TYPE_CARBO:
|
||||
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||
case RecordTypes.RECORD_TYPE_ERROR:
|
||||
case RecordTypes.RECORD_TYPE_PRIME:
|
||||
case RecordTypes.RECORD_TYPE_REFILL:
|
||||
case RecordTypes.RECORD_TYPE_TB:
|
||||
holder.time.setVisibility(View.VISIBLE);
|
||||
holder.value.setVisibility(View.VISIBLE);
|
||||
holder.stringvalue.setVisibility(View.GONE);
|
||||
holder.bolustype.setVisibility(View.GONE);
|
||||
holder.duration.setVisibility(View.GONE);
|
||||
holder.dailybasal.setVisibility(View.GONE);
|
||||
holder.dailybolus.setVisibility(View.GONE);
|
||||
holder.dailytotal.setVisibility(View.GONE);
|
||||
holder.alarm.setVisibility(View.GONE);
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_SUSPEND:
|
||||
holder.time.setVisibility(View.VISIBLE);
|
||||
holder.value.setVisibility(View.GONE);
|
||||
holder.stringvalue.setVisibility(View.VISIBLE);
|
||||
holder.bolustype.setVisibility(View.GONE);
|
||||
holder.duration.setVisibility(View.GONE);
|
||||
holder.dailybasal.setVisibility(View.GONE);
|
||||
holder.dailybolus.setVisibility(View.GONE);
|
||||
holder.dailytotal.setVisibility(View.GONE);
|
||||
holder.alarm.setVisibility(View.GONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return historyList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
public static class HistoryViewHolder extends RecyclerView.ViewHolder {
|
||||
CardView cv;
|
||||
TextView time;
|
||||
TextView value;
|
||||
TextView bolustype;
|
||||
TextView stringvalue;
|
||||
TextView duration;
|
||||
TextView dailybasal;
|
||||
TextView dailybolus;
|
||||
TextView dailytotal;
|
||||
TextView alarm;
|
||||
|
||||
HistoryViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
cv = (CardView) itemView.findViewById(R.id.danar_history_cardview);
|
||||
time = (TextView) itemView.findViewById(R.id.danar_history_time);
|
||||
value = (TextView) itemView.findViewById(R.id.danar_history_value);
|
||||
bolustype = (TextView) itemView.findViewById(R.id.danar_history_bolustype);
|
||||
stringvalue = (TextView) itemView.findViewById(R.id.danar_history_stringvalue);
|
||||
duration = (TextView) itemView.findViewById(R.id.danar_history_duration);
|
||||
dailybasal = (TextView) itemView.findViewById(R.id.danar_history_dailybasal);
|
||||
dailybolus = (TextView) itemView.findViewById(R.id.danar_history_dailybolus);
|
||||
dailytotal = (TextView) itemView.findViewById(R.id.danar_history_dailytotal);
|
||||
alarm = (TextView) itemView.findViewById(R.id.danar_history_alarm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDataFromDB(byte type) {
|
||||
try {
|
||||
Dao<DanaRHistoryRecord, String> dao = MainApp.getDbHelper().getDaoDanaRHistory();
|
||||
QueryBuilder<DanaRHistoryRecord, String> queryBuilder = dao.queryBuilder();
|
||||
queryBuilder.orderBy("recordDate", false);
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("recordCode", type);
|
||||
queryBuilder.limit(200L);
|
||||
PreparedQuery<DanaRHistoryRecord> preparedQuery = queryBuilder.prepare();
|
||||
historyList = dao.query(preparedQuery);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
historyList = new ArrayList<>();
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearCardView() {
|
||||
historyList = new ArrayList<>();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDanaRSyncStatus s) {
|
||||
log.debug("EventDanaRSyncStatus: " + s.message);
|
||||
runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
statusView.setText(s.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventDanaRConnectionStatus c) {
|
||||
runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (c.sStatus == EventDanaRConnectionStatus.CONNECTING) {
|
||||
statusView.setText(String.format(getString(R.string.danar_history_connectingfor), c.sSecondsElapsed));
|
||||
log.debug("EventDanaRConnectionStatus: " + "Connecting for " + c.sSecondsElapsed + "s");
|
||||
} else if (c.sStatus == EventDanaRConnectionStatus.CONNECTED) {
|
||||
statusView.setText(MainApp.sResources.getString(R.string.connected));
|
||||
log.debug("EventDanaRConnectionStatus: Connected");
|
||||
} else {
|
||||
statusView.setText(MainApp.sResources.getString(R.string.disconnected));
|
||||
log.debug("EventDanaRConnectionStatus: Disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean;
|
||||
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MessageHashTable;
|
||||
import info.nightscout.utils.CRC;
|
||||
|
||||
/**
|
||||
* Created by mike on 17.07.2016.
|
||||
*/
|
||||
public class SerialIOThread extends Thread {
|
||||
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
||||
|
||||
private InputStream mInputStream = null;
|
||||
private OutputStream mOutputStream = null;
|
||||
private BluetoothSocket mRfCommSocket;
|
||||
|
||||
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledDisconnection = null;
|
||||
|
||||
private boolean mKeepRunning = true;
|
||||
private byte[] mReadBuff = new byte[0];
|
||||
|
||||
MessageBase processedMessage;
|
||||
|
||||
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
||||
super(SerialIOThread.class.toString());
|
||||
|
||||
mRfCommSocket = rfcommSocket;
|
||||
try {
|
||||
mOutputStream = mRfCommSocket.getOutputStream();
|
||||
mInputStream = mRfCommSocket.getInputStream();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
try {
|
||||
while (mKeepRunning) {
|
||||
int availableBytes = mInputStream.available();
|
||||
// Ask for 1024 byte (or more if available)
|
||||
byte[] newData = new byte[Math.max(1024, availableBytes)];
|
||||
int gotBytes = mInputStream.read(newData);
|
||||
// When we are here there is some new data available
|
||||
appendToBuffer(newData, gotBytes);
|
||||
|
||||
// process all messages we already got
|
||||
while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size
|
||||
byte[] extractedBuff = cutMessageFromBuffer();
|
||||
if (extractedBuff == null) break; // message is not complete in buffer (wrong packet calls disconnection)
|
||||
|
||||
int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00);
|
||||
|
||||
MessageBase message;
|
||||
if (processedMessage != null && processedMessage.getCommand() == command) {
|
||||
message = processedMessage;
|
||||
} else {
|
||||
// get it from hash table
|
||||
message = MessageHashTable.findMessage(command);
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff));
|
||||
|
||||
// process the message content
|
||||
message.received = true;
|
||||
message.handleMessage(extractedBuff);
|
||||
synchronized (message) {
|
||||
message.notify();
|
||||
}
|
||||
scheduleDisconnection();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (Config.logDanaSerialEngine && e.getMessage().indexOf("bt socket closed") < 0)
|
||||
log.error("Thread exception: ", e);
|
||||
mKeepRunning = false;
|
||||
}
|
||||
disconnect("EndOfLoop");
|
||||
}
|
||||
|
||||
void appendToBuffer(byte[] newData, int gotBytes) {
|
||||
// add newData to mReadBuff
|
||||
byte[] newReadBuff = new byte[mReadBuff.length + gotBytes];
|
||||
System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length);
|
||||
System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes);
|
||||
mReadBuff = newReadBuff;
|
||||
}
|
||||
|
||||
byte[] cutMessageFromBuffer() {
|
||||
if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) {
|
||||
int length = (mReadBuff[2] & 0xFF) + 7;
|
||||
// Check if we have enough data
|
||||
if (mReadBuff.length < length) {
|
||||
return null;
|
||||
}
|
||||
if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) {
|
||||
log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff));
|
||||
disconnect("wrong packet");
|
||||
return null;
|
||||
}
|
||||
|
||||
short crc = CRC.getCrc16(mReadBuff, 3, length - 7);
|
||||
byte crcByte0 = (byte) (crc >> 8 & 0xFF);
|
||||
byte crcByte1 = (byte) (crc & 0xFF);
|
||||
|
||||
byte crcByte0received = mReadBuff[length - 4];
|
||||
byte crcByte1received = mReadBuff[length - 3];
|
||||
|
||||
if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) {
|
||||
log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received));
|
||||
disconnect("crc error");
|
||||
return null;
|
||||
}
|
||||
// Packet is verified here. extract data
|
||||
byte[] extractedBuff = new byte[length];
|
||||
System.arraycopy(mReadBuff, 0, extractedBuff, 0, length);
|
||||
// remove extracted data from read buffer
|
||||
byte[] unprocessedData = new byte[mReadBuff.length - length];
|
||||
System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length);
|
||||
mReadBuff = unprocessedData;
|
||||
return extractedBuff;
|
||||
} else {
|
||||
log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff));
|
||||
disconnect("Wrong beginning of packet");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void sendMessage(MessageBase message) {
|
||||
if (!mRfCommSocket.isConnected()) {
|
||||
log.error("Socket not connected on sendMessage");
|
||||
return;
|
||||
}
|
||||
processedMessage = message;
|
||||
|
||||
byte[] messageBytes = message.getRawMessageBytes();
|
||||
if (Config.logDanaSerialEngine)
|
||||
log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes));
|
||||
|
||||
try {
|
||||
mOutputStream.write(messageBytes);
|
||||
} catch (Exception e) {
|
||||
log.error("sendMessage write exception: ", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
synchronized (message) {
|
||||
try {
|
||||
message.wait(5000);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("sendMessage InterruptedException", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (!message.received) {
|
||||
log.warn("Reply not received " + message.getMessageName());
|
||||
}
|
||||
scheduleDisconnection();
|
||||
}
|
||||
|
||||
public void scheduleDisconnection() {
|
||||
class DisconnectRunnable implements Runnable {
|
||||
public void run() {
|
||||
disconnect("scheduleDisconnection");
|
||||
scheduledDisconnection = null;
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 5 sec
|
||||
// cancel waiting task to prevent sending multiple disconnections
|
||||
if (scheduledDisconnection != null)
|
||||
scheduledDisconnection.cancel(false);
|
||||
Runnable task = new DisconnectRunnable();
|
||||
final int sec = 5;
|
||||
scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void disconnect(String reason) {
|
||||
mKeepRunning = false;
|
||||
try {
|
||||
mInputStream.close();
|
||||
} catch (Exception e) {
|
||||
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||
}
|
||||
try {
|
||||
mOutputStream.close();
|
||||
} catch (Exception e) {
|
||||
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||
}
|
||||
try {
|
||||
mRfCommSocket.close();
|
||||
} catch (Exception e) {
|
||||
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||
}
|
||||
try {
|
||||
System.runFinalization();
|
||||
} catch (Exception e) {
|
||||
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
|
||||
}
|
||||
if (Config.logDanaSerialEngine) log.debug("Disconnected: " + reason);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.Services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAlarm;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBasalHour;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBolus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryCarbo;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDailyInsulin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDone;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryError;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryGlucose;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryRefill;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistorySuspend;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetCarbsEntry;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetSingleBasalProfile;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTime;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.SerialIOThread;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgCheckValue;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingBasal;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingGlucose;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingMaxValues;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingMeal;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingProfileRatios;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingPumpTime;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingShippingInfo;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusBasic;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusBolusExtended;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusTempBasal;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class ExecutionService extends Service {
|
||||
private static Logger log = LoggerFactory.getLogger(ExecutionService.class);
|
||||
|
||||
private SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
private String devName;
|
||||
|
||||
private SerialIOThread mSerialIOThread;
|
||||
private BluetoothSocket mRfcommSocket;
|
||||
private BluetoothDevice mBTDevice;
|
||||
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private IBinder mBinder = new LocalBinder();
|
||||
|
||||
private DanaRKoreanPump danaRKoreanPump;
|
||||
private Treatment bolusingTreatment = null;
|
||||
|
||||
private static Boolean connectionInProgress = false;
|
||||
private static final Object connectionLock = new Object();
|
||||
|
||||
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
String action = intent.getAction();
|
||||
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
|
||||
log.debug("Device has disconnected " + device.getName());//Device has disconnected
|
||||
if (mBTDevice != null && mBTDevice.getName().equals(device.getName())) {
|
||||
if (mSerialIOThread != null) {
|
||||
mSerialIOThread.disconnect("BT disconnection broadcast");
|
||||
}
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.DISCONNECTED, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ExecutionService() {
|
||||
registerBus();
|
||||
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
|
||||
danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump();
|
||||
|
||||
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExecutionService");
|
||||
}
|
||||
|
||||
public class LocalBinder extends Binder {
|
||||
public ExecutionService getServiceInstance() {
|
||||
return ExecutionService.this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private void registerBus() {
|
||||
try {
|
||||
MainApp.bus().unregister(this);
|
||||
} catch (RuntimeException x) {
|
||||
// Ignore
|
||||
}
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(EventAppExit event) {
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("EventAppExit received");
|
||||
|
||||
if (mSerialIOThread != null)
|
||||
mSerialIOThread.disconnect("Application exit");
|
||||
|
||||
MainApp.instance().getApplicationContext().unregisterReceiver(receiver);
|
||||
|
||||
stopSelf();
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("EventAppExit finished");
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return mRfcommSocket != null && mRfcommSocket.isConnected();
|
||||
}
|
||||
|
||||
public boolean isConnecting() {
|
||||
return connectionInProgress;
|
||||
}
|
||||
|
||||
public void disconnect(String from) {
|
||||
if (mSerialIOThread != null)
|
||||
mSerialIOThread.disconnect(from);
|
||||
}
|
||||
|
||||
public void connect(String from) {
|
||||
if (danaRKoreanPump.password != -1 && danaRKoreanPump.password != SafeParse.stringToInt(SP.getString("danar_password", "-1"))) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
||||
return;
|
||||
}
|
||||
while (isConnected() || isConnecting()) {
|
||||
if (Config.logDanaBTComm)
|
||||
log.debug("already connected/connecting from: " + from);
|
||||
waitMsec(3000);
|
||||
}
|
||||
final long maxConnectionTime = 5 * 60 * 1000L; // 5 min
|
||||
synchronized (connectionLock) {
|
||||
//log.debug("entering connection while loop");
|
||||
connectionInProgress = true;
|
||||
mWakeLock.acquire();
|
||||
getBTSocketForSelectedPump();
|
||||
if (mRfcommSocket == null || mBTDevice == null)
|
||||
return; // Device not found
|
||||
long startTime = new Date().getTime();
|
||||
while (!isConnected() && startTime + maxConnectionTime >= new Date().getTime()) {
|
||||
long secondsElapsed = (new Date().getTime() - startTime) / 1000L;
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.CONNECTING, (int) secondsElapsed));
|
||||
if (Config.logDanaBTComm)
|
||||
log.debug("connect waiting " + secondsElapsed + "sec from: " + from);
|
||||
try {
|
||||
mRfcommSocket.connect();
|
||||
} catch (IOException e) {
|
||||
//e.printStackTrace();
|
||||
if (e.getMessage().contains("socket closed")) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
waitMsec(1000);
|
||||
|
||||
if (isConnected()) {
|
||||
if (mSerialIOThread != null) {
|
||||
mSerialIOThread.disconnect("Recreate SerialIOThread");
|
||||
}
|
||||
mSerialIOThread = new SerialIOThread(mRfcommSocket);
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.CONNECTED, 0));
|
||||
if (!getPumpStatus()) {
|
||||
mSerialIOThread.disconnect("getPumpStatus failed");
|
||||
waitMsec(3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isConnected()) {
|
||||
MainApp.bus().post(new EventDanaRConnectionStatus(EventDanaRConnectionStatus.DISCONNECTED, 0));
|
||||
log.error("Pump connection timed out");
|
||||
}
|
||||
connectionInProgress = false;
|
||||
mWakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void getBTSocketForSelectedPump() {
|
||||
devName = SP.getString("danar_bt_name", "");
|
||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
if (bluetoothAdapter != null) {
|
||||
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
|
||||
|
||||
for (BluetoothDevice device : bondedDevices) {
|
||||
if (devName.equals(device.getName())) {
|
||||
mBTDevice = device;
|
||||
try {
|
||||
mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating socket: ", e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter));
|
||||
}
|
||||
if (mBTDevice == null) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventPreferenceChange pch) {
|
||||
if (mSerialIOThread != null)
|
||||
mSerialIOThread.disconnect("EventPreferenceChange");
|
||||
}
|
||||
|
||||
private boolean getPumpStatus() {
|
||||
try {
|
||||
//MsgStatus statusMsg = new MsgStatus();
|
||||
MsgStatusBasic statusBasicMsg = new MsgStatusBasic();
|
||||
MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal();
|
||||
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||
|
||||
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
|
||||
mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
|
||||
mSerialIOThread.sendMessage(exStatusMsg);
|
||||
//mSerialIOThread.sendMessage(statusMsg);
|
||||
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||
|
||||
mSerialIOThread.sendMessage(new MsgCheckValue());
|
||||
|
||||
// if (!statusMsg.received) {
|
||||
// mSerialIOThread.sendMessage(statusMsg);
|
||||
// }
|
||||
if (!statusBasicMsg.received) {
|
||||
mSerialIOThread.sendMessage(statusBasicMsg);
|
||||
}
|
||||
if (!tempStatusMsg.received) {
|
||||
// Load of status of current basal rate failed, give one more try
|
||||
mSerialIOThread.sendMessage(tempStatusMsg);
|
||||
}
|
||||
if (!exStatusMsg.received) {
|
||||
// Load of status of current extended bolus failed, give one more try
|
||||
mSerialIOThread.sendMessage(exStatusMsg);
|
||||
}
|
||||
|
||||
// Check we have really current status of pump
|
||||
if (/*!statusMsg.received || */!statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) {
|
||||
waitMsec(10 * 1000);
|
||||
log.debug("getPumpStatus failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
if (danaRKoreanPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).isInitialized()) {
|
||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
||||
mSerialIOThread.sendMessage(new MsgSettingMeal());
|
||||
mSerialIOThread.sendMessage(new MsgSettingBasal());
|
||||
//0x3201
|
||||
mSerialIOThread.sendMessage(new MsgSettingMaxValues());
|
||||
mSerialIOThread.sendMessage(new MsgSettingGlucose());
|
||||
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
||||
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
|
||||
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
|
||||
danaRKoreanPump.lastSettingsRead = now;
|
||||
}
|
||||
|
||||
danaRKoreanPump.lastConnection = now;
|
||||
MainApp.bus().post(new EventDanaRNewStatus());
|
||||
MainApp.bus().post(new EventInitializationChanged());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean tempBasal(int percent, int durationInHours) {
|
||||
connect("tempBasal");
|
||||
if (!isConnected()) return false;
|
||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
||||
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean tempBasalStop() {
|
||||
connect("tempBasalStop");
|
||||
if (!isConnected()) return false;
|
||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
||||
mSerialIOThread.sendMessage(new MsgStatusTempBasal());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean extendedBolus(double insulin, int durationInHalfHours) {
|
||||
connect("extendedBolus");
|
||||
if (!isConnected()) return false;
|
||||
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF)));
|
||||
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean extendedBolusStop() {
|
||||
connect("extendedBolusStop");
|
||||
if (!isConnected()) return false;
|
||||
mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop());
|
||||
mSerialIOThread.sendMessage(new MsgStatusBolusExtended());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean bolus(Double amount, int carbs, Treatment t) {
|
||||
bolusingTreatment = t;
|
||||
MsgBolusStart start = new MsgBolusStart(amount);
|
||||
MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables
|
||||
MsgBolusStop stop = new MsgBolusStop(amount, t);
|
||||
|
||||
connect("bolus");
|
||||
if (!isConnected()) return false;
|
||||
|
||||
if (carbs > 0) {
|
||||
Calendar time = Calendar.getInstance();
|
||||
mSerialIOThread.sendMessage(new MsgSetCarbsEntry(time, carbs));
|
||||
}
|
||||
MainApp.bus().post(new EventDanaRBolusStart());
|
||||
|
||||
if (!stop.stopped) {
|
||||
mSerialIOThread.sendMessage(start);
|
||||
} else {
|
||||
t.insulin = 0d;
|
||||
return false;
|
||||
}
|
||||
while (!stop.stopped && !start.failed) {
|
||||
waitMsec(100);
|
||||
if (progress.lastReceive != 0 && (new Date().getTime() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm
|
||||
stop.stopped = true;
|
||||
stop.forced = true;
|
||||
log.debug("Communication stopped");
|
||||
}
|
||||
}
|
||||
waitMsec(300);
|
||||
bolusingTreatment = null;
|
||||
getPumpStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void bolusStop() {
|
||||
if (Config.logDanaBTComm)
|
||||
log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
|
||||
MsgBolusStop stop = new MsgBolusStop();
|
||||
stop.forced = true;
|
||||
if (isConnected()) {
|
||||
mSerialIOThread.sendMessage(stop);
|
||||
while (!stop.stopped) {
|
||||
mSerialIOThread.sendMessage(stop);
|
||||
waitMsec(200);
|
||||
}
|
||||
} else {
|
||||
stop.stopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean carbsEntry(int amount) {
|
||||
connect("carbsEntry");
|
||||
if (!isConnected()) return false;
|
||||
Calendar time = Calendar.getInstance();
|
||||
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount);
|
||||
mSerialIOThread.sendMessage(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean loadHistory(byte type) {
|
||||
connect("loadHistory");
|
||||
if (!isConnected()) return false;
|
||||
MessageBase msg = null;
|
||||
switch (type) {
|
||||
case RecordTypes.RECORD_TYPE_ALARM:
|
||||
msg = new MsgHistoryAlarm();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||
msg = new MsgHistoryBasalHour();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||
msg = new MsgHistoryBolus();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_CARBO:
|
||||
msg = new MsgHistoryCarbo();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_DAILY:
|
||||
msg = new MsgHistoryDailyInsulin();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_ERROR:
|
||||
msg = new MsgHistoryError();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||
msg = new MsgHistoryGlucose();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_REFILL:
|
||||
msg = new MsgHistoryRefill();
|
||||
break;
|
||||
case RecordTypes.RECORD_TYPE_SUSPEND:
|
||||
msg = new MsgHistorySuspend();
|
||||
break;
|
||||
}
|
||||
MsgHistoryDone done = new MsgHistoryDone();
|
||||
mSerialIOThread.sendMessage(new MsgPCCommStart());
|
||||
waitMsec(400);
|
||||
mSerialIOThread.sendMessage(msg);
|
||||
while (!done.received && mRfcommSocket.isConnected()) {
|
||||
waitMsec(100);
|
||||
}
|
||||
waitMsec(200);
|
||||
mSerialIOThread.sendMessage(new MsgPCCommStop());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean updateBasalsInPump(final NSProfile profile) {
|
||||
connect("updateBasalsInPump");
|
||||
if (!isConnected()) return false;
|
||||
double[] basal = buildDanaRProfileRecord(profile);
|
||||
MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal);
|
||||
mSerialIOThread.sendMessage(msgSet);
|
||||
danaRKoreanPump.lastSettingsRead = new Date(0); // force read full settings
|
||||
getPumpStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
private double[] buildDanaRProfileRecord(NSProfile nsProfile) {
|
||||
double[] record = new double[24];
|
||||
for (Integer hour = 0; hour < 24; hour++) {
|
||||
double value = nsProfile.getBasal(hour * 60 * 60);
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("NS basal value for " + hour + ":00 is " + value);
|
||||
record[hour] = value;
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
private void waitMsec(long msecs) {
|
||||
try {
|
||||
Thread.sleep(msecs);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgError;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAlarm;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAll;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBolus;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryCarbo;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDailyInsulin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryGlucose;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryNew;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryNewDone;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetCarbsEntry;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetSingleBasalProfile;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop;
|
||||
|
||||
/**
|
||||
* Created by mike on 28.05.2016.
|
||||
*/
|
||||
public class MessageHashTable {
|
||||
private static Logger log = LoggerFactory.getLogger(MessageHashTable.class);
|
||||
|
||||
public static HashMap<Integer, MessageBase> messages = null;
|
||||
|
||||
static {
|
||||
if (messages == null) {
|
||||
messages = new HashMap<Integer, MessageBase>();
|
||||
put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP
|
||||
put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA
|
||||
put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS
|
||||
put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING
|
||||
put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE
|
||||
put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I
|
||||
put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I
|
||||
put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS
|
||||
put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO
|
||||
put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO
|
||||
put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO
|
||||
put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S
|
||||
put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S
|
||||
put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP
|
||||
put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP
|
||||
put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S
|
||||
put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS
|
||||
put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT
|
||||
put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT
|
||||
put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS
|
||||
put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS
|
||||
put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE
|
||||
put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM
|
||||
put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY
|
||||
put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I
|
||||
put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I
|
||||
put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I
|
||||
put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I
|
||||
put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL
|
||||
put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I
|
||||
put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY
|
||||
put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I
|
||||
put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S
|
||||
put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL
|
||||
put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE
|
||||
put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW
|
||||
put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
public static void put(MessageBase message) {
|
||||
int command = message.getCommand();
|
||||
//String name = MessageOriginalNames.getName(command);
|
||||
messages.put(command, message);
|
||||
//log.debug(String.format("%04x ", command) + " " + name);
|
||||
}
|
||||
|
||||
public static MessageBase findMessage(Integer command) {
|
||||
if (messages.containsKey(command)) {
|
||||
return messages.get(command);
|
||||
} else {
|
||||
return new MessageBase();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* Created by mike on 30.06.2016.
|
||||
*/
|
||||
public class MsgCheckValue extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgCheckValue.class);
|
||||
|
||||
public MsgCheckValue() {
|
||||
SetCommand(0xF0F1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
|
||||
pump.model = intFromBuff(bytes, 0, 1);
|
||||
pump.protocol = intFromBuff(bytes, 1, 1);
|
||||
pump.productCode = intFromBuff(bytes, 2, 1);
|
||||
if (pump.model != DanaRKoreanPump.DOMESTIC_MODEL) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error);
|
||||
((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model");
|
||||
log.debug("Wrong model selected");
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Model: " + String.format("%02X ", pump.model));
|
||||
log.debug("Protocol: " + String.format("%02X ", pump.protocol));
|
||||
log.debug("Product Code: " + String.format("%02X ", pump.productCode));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
|
||||
public class MsgInitConnStatusBasic extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic.class);
|
||||
|
||||
public MsgInitConnStatusBasic() {
|
||||
SetCommand(0x0303);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
if (bytes.length - 10 > 6) {
|
||||
return;
|
||||
}
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
int isStatusSuspendOn = intFromBuff(bytes, 0, 1);
|
||||
int isUtilityEnable = intFromBuff(bytes, 1, 1);
|
||||
pump.isEasyModeEnabled = intFromBuff(bytes, 2, 1) == 1;
|
||||
int easyUIMode = intFromBuff(bytes, 3, 1);
|
||||
pump.password = intFromBuff(bytes, 4, 2) ^ 0x3463;
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("isStatusSuspendOn: " + isStatusSuspendOn);
|
||||
log.debug("isUtilityEnable: " + isUtilityEnable);
|
||||
log.debug("Is EasyUI Enabled: " + pump.isEasyModeEnabled);
|
||||
log.debug("easyUIMode: " + easyUIMode);
|
||||
log.debug("Pump password: " + pump.password);
|
||||
}
|
||||
|
||||
if (pump.isEasyModeEnabled) {
|
||||
Notification notification = new Notification(Notification.EASYMODE_ENABLED, MainApp.sResources.getString(R.string.danar_disableeasymode), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.EASYMODE_ENABLED));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
|
||||
/**
|
||||
* Created by mike on 28.05.2016.
|
||||
*/
|
||||
public class MsgInitConnStatusBolus extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBolus.class);
|
||||
|
||||
public MsgInitConnStatusBolus() {
|
||||
SetCommand(0x0302);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
if (bytes.length - 10 < 13) {
|
||||
return;
|
||||
}
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
int bolusConfig = intFromBuff(bytes, 0, 1);
|
||||
pump.isExtendedBolusEnabled = (bolusConfig & 0x01) != 0;
|
||||
|
||||
pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d;
|
||||
pump.maxBolus = intFromBuff(bytes, 2, 2) / 100d;
|
||||
//int bolusRate = intFromBuff(bytes, 4, 8);
|
||||
int deliveryStatus = intFromBuff(bytes, 12, 1);
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Is Extended bolus enabled: " + pump.isExtendedBolusEnabled);
|
||||
log.debug("Bolus increment: " + pump.bolusStep);
|
||||
log.debug("Bolus max: " + pump.maxBolus);
|
||||
log.debug("Delivery status: " + deliveryStatus);
|
||||
}
|
||||
|
||||
if (!pump.isExtendedBolusEnabled) {
|
||||
Notification notification = new Notification(Notification.EXTENDED_BOLUS_DISABLED, MainApp.sResources.getString(R.string.danar_enableextendedbolus), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class MsgInitConnStatusTime extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime.class);
|
||||
|
||||
public MsgInitConnStatusTime() {
|
||||
SetCommand(0x0301);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(byte[] bytes) {
|
||||
|
||||
if (bytes.length - 10 < 10) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error);
|
||||
((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model");
|
||||
log.debug("Wrong model selected. Switching to export DanaR");
|
||||
((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PUMP, false);
|
||||
((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentVisible(PluginBase.PUMP, false);
|
||||
((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true);
|
||||
((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, true);
|
||||
|
||||
//If profile coming from pump, switch it as well
|
||||
if(MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)){
|
||||
(MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false);
|
||||
(MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true);
|
||||
}
|
||||
|
||||
MainApp.getConfigBuilder().storeSettings();
|
||||
MainApp.bus().post(new EventRefreshGui(false));
|
||||
return;
|
||||
}
|
||||
|
||||
Date time = dateTimeSecFromBuff(bytes, 0);
|
||||
int versionCode1 = intFromBuff(bytes, 6, 1);
|
||||
int versionCode2 = intFromBuff(bytes, 7, 1);
|
||||
int versionCode3 = intFromBuff(bytes, 8, 1);
|
||||
int versionCode4 = intFromBuff(bytes, 9, 1);
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump time: " + time);
|
||||
log.debug("Version code1: " + versionCode1);
|
||||
log.debug("Version code2: " + versionCode2);
|
||||
log.debug("Version code3: " + versionCode3);
|
||||
log.debug("Version code4: " + versionCode4);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
*/
|
||||
public class MsgSettingBasal extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingBasal.class);
|
||||
|
||||
public MsgSettingBasal() {
|
||||
SetCommand(0x3202);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][];
|
||||
pump.pumpProfiles[pump.activeProfile] = new double[24];
|
||||
for (int index = 0; index < 24; index++) {
|
||||
int basal = intFromBuff(bytes, 2 * index, 2);
|
||||
if (basal < 10) basal = 0;
|
||||
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail)
|
||||
for (int index = 0; index < 24; index++) {
|
||||
log.debug("Basal " + String.format("%02d", index) + "h: " + DanaRKoreanPlugin.getDanaRPump().pumpProfiles[DanaRKoreanPlugin.getDanaRPump().activeProfile][index]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* THIS IS BROKEN IN PUMP... SENDING ONLY 1 PROFILE
|
||||
*/
|
||||
public class MsgSettingBasalProfileAll extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingBasalProfileAll.class);
|
||||
|
||||
public MsgSettingBasalProfileAll() {
|
||||
SetCommand(0x3206);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
if (DanaRKoreanPlugin.getDanaRPump().basal48Enable) {
|
||||
pump.pumpProfiles = new double[4][];
|
||||
for (int profile = 0; profile < 4; profile++) {
|
||||
int position = intFromBuff(bytes, 107 * profile, 1);
|
||||
pump.pumpProfiles[position] = new double[48];
|
||||
for (int index = 0; index < 48; index++) {
|
||||
int basal = intFromBuff(bytes, 107 * profile + 2 * index + 1, 2);
|
||||
if (basal < 10) basal = 0;
|
||||
pump.pumpProfiles[position][index] = basal / 100 / 24d; // in units/day
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pump.pumpProfiles = new double[4][];
|
||||
for (int profile = 0; profile < 4; profile++) {
|
||||
int position = intFromBuff(bytes, 49 * profile, 1);
|
||||
log.debug("position " + position);
|
||||
pump.pumpProfiles[position] = new double[24];
|
||||
for (int index = 0; index < 24; index++) {
|
||||
int basal = intFromBuff(bytes, 59 * profile + 2 * index + 1, 2);
|
||||
if (basal < 10) basal = 0;
|
||||
log.debug("position " + position + " index " + index);
|
||||
pump.pumpProfiles[position][index] = basal / 100 / 24d; // in units/day
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
if (DanaRKoreanPlugin.getDanaRPump().basal48Enable) {
|
||||
for (int profile = 0; profile < 4; profile++) {
|
||||
for (int index = 0; index < 24; index++) {
|
||||
log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + DanaRKoreanPlugin.getDanaRPump().pumpProfiles[profile][index]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int profile = 0; profile < 4; profile++) {
|
||||
for (int index = 0; index < 48; index++) {
|
||||
log.debug("Basal profile " + profile + ": " +
|
||||
String.format("%02d", (index / 2)) +
|
||||
":" + String.format("%02d", (index % 2) * 30) + " : " +
|
||||
DanaRKoreanPlugin.getDanaRPump().pumpProfiles[profile][index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
*/
|
||||
public class MsgSettingGlucose extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingGlucose.class);
|
||||
|
||||
public MsgSettingGlucose() {
|
||||
SetCommand(0x3209);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPlugin.getDanaRPump().units = intFromBuff(bytes, 0, 1);
|
||||
DanaRKoreanPlugin.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1);
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump units: " + (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL ? "MGDL" : "MMOL"));
|
||||
log.debug("Easy basal mode: " + DanaRKoreanPlugin.getDanaRPump().easyBasalMode);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
*/
|
||||
public class MsgSettingMaxValues extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingMaxValues.class);
|
||||
|
||||
public MsgSettingMaxValues() {
|
||||
SetCommand(0x3205);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPlugin.getDanaRPump().maxBolus = intFromBuff(bytes, 0, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().maxBasal = intFromBuff(bytes, 2, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100;
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Max bolus: " + DanaRKoreanPlugin.getDanaRPump().maxBolus);
|
||||
log.debug("Max basal: " + DanaRKoreanPlugin.getDanaRPump().maxBasal);
|
||||
log.debug("Total daily max units: " + DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
import info.nightscout.androidaps.plugins.Overview.Notification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
|
||||
/**
|
||||
* Created by mike on 13.12.2016.
|
||||
*/
|
||||
|
||||
public class MsgSettingMeal extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingMeal.class);
|
||||
|
||||
public MsgSettingMeal() {
|
||||
SetCommand(0x3203);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
pump.basalStep = intFromBuff(bytes, 0, 1) / 100d;
|
||||
pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d;
|
||||
boolean bolusEnabled = intFromBuff(bytes, 2, 1) == 1;
|
||||
int melodyTime = intFromBuff(bytes, 3, 1);
|
||||
int blockTime = intFromBuff(bytes, 4, 1);
|
||||
pump.isConfigUD = intFromBuff(bytes, 5, 1) == 1;
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Basal step: " + pump.basalStep);
|
||||
log.debug("Bolus step: " + pump.bolusStep);
|
||||
log.debug("Bolus enabled: " + bolusEnabled);
|
||||
log.debug("Melody time: " + melodyTime);
|
||||
log.debug("Block time: " + blockTime);
|
||||
log.debug("Is Config U/d: " + pump.isConfigUD);
|
||||
}
|
||||
|
||||
if (pump.isConfigUD) {
|
||||
Notification notification = new Notification(Notification.UD_MODE_ENABLED, MainApp.sResources.getString(R.string.danar_switchtouhmode), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.UD_MODE_ENABLED));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
*/
|
||||
public class MsgSettingProfileRatios extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatios.class);
|
||||
|
||||
public MsgSettingProfileRatios() {
|
||||
SetCommand(0x3204);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
if (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL) {
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1);
|
||||
} else {
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1);
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump units (saved): " + (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL ? "MGDL" : "MMOL"));
|
||||
log.debug("Current pump CIR: " + DanaRKoreanPlugin.getDanaRPump().currentCIR);
|
||||
log.debug("Current pump CF: " + DanaRKoreanPlugin.getDanaRPump().currentCF);
|
||||
log.debug("Current pump AI: " + DanaRKoreanPlugin.getDanaRPump().currentAI);
|
||||
log.debug("Current pump target: " + DanaRKoreanPlugin.getDanaRPump().currentTarget);
|
||||
log.debug("Current pump AIDR: " + DanaRKoreanPlugin.getDanaRPump().currentAIDR);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
|
||||
public class MsgSettingPumpTime extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class);
|
||||
|
||||
public MsgSettingPumpTime() {
|
||||
SetCommand(0x320A);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
Date time =
|
||||
new Date(
|
||||
100 + intFromBuff(bytes, 5, 1),
|
||||
intFromBuff(bytes, 4, 1) - 1,
|
||||
intFromBuff(bytes, 3, 1),
|
||||
intFromBuff(bytes, 2, 1),
|
||||
intFromBuff(bytes, 1, 1),
|
||||
intFromBuff(bytes, 0, 1)
|
||||
);
|
||||
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("Pump time: " + time);
|
||||
|
||||
DanaRKoreanPlugin.getDanaRPump().pumpTime = time;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
*/
|
||||
public class MsgSettingShippingInfo extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgSettingShippingInfo.class);
|
||||
|
||||
public MsgSettingShippingInfo() {
|
||||
SetCommand(0x3207);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump();
|
||||
pump.serialNumber = stringFromBuff(bytes, 0, 10);
|
||||
pump.shippingDate = dateFromBuff(bytes, 10);
|
||||
pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3);
|
||||
if (pump.shippingDate.getTime() > new Date(116, 4, 1).getTime()) {
|
||||
pump.isNewPump = true;
|
||||
} else
|
||||
pump.isNewPump = false;
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Serial number: " + pump.serialNumber);
|
||||
log.debug("Shipping date: " + pump.shippingDate);
|
||||
log.debug("Shipping country: " + pump.shippingCountry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
|
||||
public class MsgStatus extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgStatus.class);
|
||||
|
||||
public MsgStatus() {
|
||||
SetCommand(0x020B);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d;
|
||||
DanaRKoreanPlugin.getDanaRPump().isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusMinutes = intFromBuff(bytes, 4, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d;
|
||||
Double lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d;
|
||||
// if (lastBolusAmount != 0d) {
|
||||
// DanaRKoreanPlugin.getDanaRPump().lastBolusTime = dateTimeFromBuff(bytes, 8);
|
||||
// DanaRKoreanPlugin.getDanaRPump().lastBolusAmount = lastBolusAmount;
|
||||
// }
|
||||
DanaRKoreanPlugin.getDanaRPump().iob = intFromBuff(bytes, 15, 2) / 100d;
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Daily total: " + DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits);
|
||||
log.debug("Is extended bolus running: " + DanaRKoreanPlugin.getDanaRPump().isExtendedInProgress);
|
||||
log.debug("Extended bolus min: " + DanaRKoreanPlugin.getDanaRPump().extendedBolusMinutes);
|
||||
log.debug("Extended bolus amount: " + DanaRKoreanPlugin.getDanaRPump().extendedBolusAmount);
|
||||
// log.debug("Last bolus time: " + DanaRKoreanPlugin.getDanaRPump().lastBolusTime);
|
||||
// log.debug("Last bolus amount: " + DanaRKoreanPlugin.getDanaRPump().lastBolusAmount);
|
||||
log.debug("IOB: " + DanaRKoreanPlugin.getDanaRPump().iob);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
|
||||
|
||||
public class MsgStatusBasic extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgStatusBasic.class);
|
||||
|
||||
public MsgStatusBasic() {
|
||||
SetCommand(0x020A);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
double currentBasal = intFromBuff(bytes, 0, 2) / 100d;
|
||||
int batteryRemaining = intFromBuff(bytes, 2, 1);
|
||||
double reservoirRemainingUnits = intFromBuff(bytes, 3, 3) / 750d;
|
||||
double dailyTotalUnits = intFromBuff(bytes, 6, 3) / 750d;
|
||||
int maxDailyTotalUnits = intFromBuff(bytes, 9, 2) / 100;
|
||||
|
||||
DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits = dailyTotalUnits;
|
||||
DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits = maxDailyTotalUnits;
|
||||
DanaRKoreanPlugin.getDanaRPump().reservoirRemainingUnits = reservoirRemainingUnits;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentBasal = currentBasal;
|
||||
DanaRKoreanPlugin.getDanaRPump().batteryRemaining = batteryRemaining;
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Daily total units: " + dailyTotalUnits);
|
||||
log.debug("Max daily total units: " + maxDailyTotalUnits);
|
||||
log.debug("Reservoir remaining units: " + reservoirRemainingUnits);
|
||||
log.debug("Current basal: " + currentBasal);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
public class MsgStatusBolusExtended extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended.class);
|
||||
|
||||
public MsgStatusBolusExtended() {
|
||||
SetCommand(0x0207);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1;
|
||||
int extendedBolusHalfHours = intFromBuff(bytes, 1, 1);
|
||||
int extendedBolusMinutes = extendedBolusHalfHours * 30;
|
||||
|
||||
double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d;
|
||||
int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3);
|
||||
int extendedBolusDeliveryPulse = intFromBuff(bytes, 7, 2);
|
||||
int isEasyUIUserSleep = intFromBuff(bytes, 9, 1);
|
||||
|
||||
int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60;
|
||||
double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d;
|
||||
Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0);
|
||||
int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes;
|
||||
|
||||
DanaRKoreanPlugin.getDanaRPump().isExtendedInProgress = isExtendedInProgress;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusMinutes = extendedBolusMinutes;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusAmount = extendedBolusAmount;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusAbsoluteRate = extendedBolusAbsoluteRate;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusStart = extendedBolusStart;
|
||||
DanaRKoreanPlugin.getDanaRPump().extendedBolusRemainingMinutes = extendedBolusRemainingMinutes;
|
||||
|
||||
updateExtendedBolusInDB();
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Is extended bolus running: " + isExtendedInProgress);
|
||||
log.debug("Extended bolus min: " + extendedBolusMinutes);
|
||||
log.debug("Extended bolus amount: " + extendedBolusAmount);
|
||||
log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes);
|
||||
log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate);
|
||||
log.debug("Extended bolus start: " + extendedBolusStart);
|
||||
log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Date getDateFromSecAgo(int tempBasalAgoSecs) {
|
||||
return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000);
|
||||
}
|
||||
|
||||
public static void updateExtendedBolusInDB() {
|
||||
DanaRKoreanPlugin DanaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
DanaRKoreanPump danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump();
|
||||
Date now = new Date();
|
||||
|
||||
try {
|
||||
|
||||
if (DanaRKoreanPlugin.isExtendedBoluslInProgress()) {
|
||||
TempBasal extendedBolus = DanaRKoreanPlugin.getExtendedBolus();
|
||||
if (danaRKoreanPump.isExtendedInProgress) {
|
||||
if (extendedBolus.absolute != danaRKoreanPump.extendedBolusAbsoluteRate) {
|
||||
// Close current extended
|
||||
extendedBolus.timeEnd = now;
|
||||
MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus);
|
||||
// Create new
|
||||
TempBasal newExtended = new TempBasal();
|
||||
newExtended.timeStart = now;
|
||||
newExtended.absolute = danaRKoreanPump.extendedBolusAbsoluteRate;
|
||||
newExtended.isAbsolute = true;
|
||||
newExtended.duration = danaRKoreanPump.extendedBolusMinutes;
|
||||
newExtended.isExtended = true;
|
||||
MainApp.getDbHelper().getDaoTempBasals().create(newExtended);
|
||||
MainApp.bus().post(new EventTempBasalChange());
|
||||
}
|
||||
} else {
|
||||
// Close curent temp basal
|
||||
extendedBolus.timeEnd = now;
|
||||
MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus);
|
||||
MainApp.bus().post(new EventTempBasalChange());
|
||||
}
|
||||
} else {
|
||||
if (danaRKoreanPump.isExtendedInProgress) {
|
||||
// Create new
|
||||
TempBasal newExtended = new TempBasal();
|
||||
newExtended.timeStart = now;
|
||||
newExtended.absolute = danaRKoreanPump.extendedBolusAbsoluteRate;
|
||||
newExtended.isAbsolute = true;
|
||||
newExtended.duration = danaRKoreanPump.extendedBolusMinutes;
|
||||
newExtended.isExtended = true;
|
||||
MainApp.getDbHelper().getDaoTempBasals().create(newExtended);
|
||||
MainApp.bus().post(new EventTempBasalChange());
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.07.2016.
|
||||
*/
|
||||
public class MsgStatusProfile extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgStatusProfile.class);
|
||||
|
||||
public MsgStatusProfile() {
|
||||
SetCommand(0x0204);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
if (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL) {
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2);
|
||||
} else {
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
|
||||
DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d;
|
||||
DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d;
|
||||
}
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Pump units (saved): " + (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL ? "MGDL" : "MMOL"));
|
||||
log.debug("Current pump CIR: " + DanaRKoreanPlugin.getDanaRPump().currentCIR);
|
||||
log.debug("Current pump CF: " + DanaRKoreanPlugin.getDanaRPump().currentCF);
|
||||
log.debug("Current pump AI: " + DanaRKoreanPlugin.getDanaRPump().currentAI);
|
||||
log.debug("Current pump target: " + DanaRKoreanPlugin.getDanaRPump().currentTarget);
|
||||
log.debug("Current pump AIDR: " + DanaRKoreanPlugin.getDanaRPump().currentAIDR);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package info.nightscout.androidaps.plugins.DanaRKorean.comm;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||
import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump;
|
||||
|
||||
public class MsgStatusTempBasal extends MessageBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal.class);
|
||||
|
||||
public MsgStatusTempBasal() {
|
||||
SetCommand(0x0205);
|
||||
}
|
||||
|
||||
public void handleMessage(byte[] bytes) {
|
||||
boolean isTempBasalInProgress = intFromBuff(bytes, 0, 1) == 1;
|
||||
int tempBasalPercent = intFromBuff(bytes, 1, 1);
|
||||
int tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60;
|
||||
int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3);
|
||||
int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60;
|
||||
Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0);
|
||||
|
||||
DanaRKoreanPlugin.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress;
|
||||
DanaRKoreanPlugin.getDanaRPump().tempBasalPercent = tempBasalPercent;
|
||||
DanaRKoreanPlugin.getDanaRPump().tempBasalRemainingMin = tempBasalRemainingMin;
|
||||
DanaRKoreanPlugin.getDanaRPump().tempBasalTotalSec = tempBasalTotalSec;
|
||||
DanaRKoreanPlugin.getDanaRPump().tempBasalStart = tempBasalStart;
|
||||
|
||||
updateTempBasalInDB();
|
||||
|
||||
if (Config.logDanaMessageDetail) {
|
||||
log.debug("Is temp basal running: " + isTempBasalInProgress);
|
||||
log.debug("Current temp basal percent: " + tempBasalPercent);
|
||||
log.debug("Current temp basal remaining min: " + tempBasalRemainingMin);
|
||||
log.debug("Current temp basal total sec: " + tempBasalTotalSec);
|
||||
log.debug("Current temp basal start: " + tempBasalStart);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) {
|
||||
return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000);
|
||||
}
|
||||
|
||||
public static void updateTempBasalInDB() {
|
||||
DanaRKoreanPlugin DanaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
DanaRKoreanPump danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump();
|
||||
Date now = new Date();
|
||||
|
||||
try {
|
||||
|
||||
if (DanaRKoreanPlugin.isRealTempBasalInProgress()) {
|
||||
TempBasal tempBasal = DanaRKoreanPlugin.getRealTempBasal();
|
||||
if (danaRKoreanPump.isTempBasalInProgress) {
|
||||
if (tempBasal.percent != danaRKoreanPump.tempBasalPercent) {
|
||||
// Close current temp basal
|
||||
tempBasal.timeEnd = now;
|
||||
MainApp.getDbHelper().getDaoTempBasals().update(tempBasal);
|
||||
// Create new
|
||||
TempBasal newTempBasal = new TempBasal();
|
||||
newTempBasal.timeStart = now;
|
||||
newTempBasal.percent = danaRKoreanPump.tempBasalPercent;
|
||||
newTempBasal.isAbsolute = false;
|
||||
newTempBasal.duration = danaRKoreanPump.tempBasalTotalSec / 60;
|
||||
newTempBasal.isExtended = false;
|
||||
MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal);
|
||||
MainApp.bus().post(new EventTempBasalChange());
|
||||
}
|
||||
} else {
|
||||
// Close current temp basal
|
||||
tempBasal.timeEnd = now;
|
||||
MainApp.getDbHelper().getDaoTempBasals().update(tempBasal);
|
||||
MainApp.bus().post(new EventTempBasalChange());
|
||||
}
|
||||
} else {
|
||||
if (danaRKoreanPump.isTempBasalInProgress) {
|
||||
// Create new
|
||||
TempBasal newTempBasal = new TempBasal();
|
||||
newTempBasal.timeStart = now;
|
||||
newTempBasal.percent = danaRKoreanPump.tempBasalPercent;
|
||||
newTempBasal.isAbsolute = false;
|
||||
newTempBasal.duration = danaRKoreanPump.tempBasalTotalSec / 60;
|
||||
newTempBasal.isExtended = false;
|
||||
MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal);
|
||||
MainApp.bus().post(new EventTempBasalChange());
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,9 +24,12 @@ import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
|
|||
public class LoopFragment extends Fragment implements View.OnClickListener, FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(LoopFragment.class);
|
||||
|
||||
private static LoopPlugin loopPlugin = new LoopPlugin();
|
||||
private static LoopPlugin loopPlugin;
|
||||
|
||||
public static LoopPlugin getPlugin() {
|
||||
if (loopPlugin == null){
|
||||
loopPlugin = new LoopPlugin();
|
||||
}
|
||||
return loopPlugin;
|
||||
}
|
||||
|
||||
|
@ -73,7 +76,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Frag
|
|||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.loop_run:
|
||||
loopPlugin.invoke(true);
|
||||
getPlugin().invoke(true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -104,13 +107,13 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Frag
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (loopPlugin.lastRun != null) {
|
||||
requestView.setText(loopPlugin.lastRun.request != null ? loopPlugin.lastRun.request.toSpanned() : "");
|
||||
constraintsProcessedView.setText(loopPlugin.lastRun.constraintsProcessed != null ? loopPlugin.lastRun.constraintsProcessed.toSpanned() : "");
|
||||
setByPumpView.setText(loopPlugin.lastRun.setByPump != null ? loopPlugin.lastRun.setByPump.toSpanned() : "");
|
||||
sourceView.setText(loopPlugin.lastRun.source != null ? loopPlugin.lastRun.source : "");
|
||||
lastRunView.setText(loopPlugin.lastRun.lastAPSRun != null && loopPlugin.lastRun.lastAPSRun.getTime() != 0 ? loopPlugin.lastRun.lastAPSRun.toLocaleString() : "");
|
||||
lastEnactView.setText(loopPlugin.lastRun.lastEnact != null && loopPlugin.lastRun.lastEnact.getTime() != 0 ? loopPlugin.lastRun.lastEnact.toLocaleString() : "");
|
||||
if (getPlugin().lastRun != null) {
|
||||
requestView.setText(getPlugin().lastRun.request != null ? getPlugin().lastRun.request.toSpanned() : "");
|
||||
constraintsProcessedView.setText(getPlugin().lastRun.constraintsProcessed != null ? getPlugin().lastRun.constraintsProcessed.toSpanned() : "");
|
||||
setByPumpView.setText(getPlugin().lastRun.setByPump != null ? getPlugin().lastRun.setByPump.toSpanned() : "");
|
||||
sourceView.setText(getPlugin().lastRun.source != null ? getPlugin().lastRun.source : "");
|
||||
lastRunView.setText(getPlugin().lastRun.lastAPSRun != null && getPlugin().lastRun.lastAPSRun.getTime() != 0 ? getPlugin().lastRun.lastAPSRun.toLocaleString() : "");
|
||||
lastEnactView.setText(getPlugin().lastRun.lastEnact != null && getPlugin().lastRun.lastEnact.getTime() != 0 ? getPlugin().lastRun.lastEnact.toLocaleString() : "");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -83,12 +83,12 @@ public class LoopPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == LOOP && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == LOOP && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,12 +98,12 @@ public class LoopPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == LOOP) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == LOOP) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -128,7 +128,7 @@ public class LoopPlugin implements PluginBase {
|
|||
final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder();
|
||||
APSResult result = null;
|
||||
|
||||
if (configBuilder == null || !isEnabled(PluginBase.GENERAL))
|
||||
if (configBuilder == null || !isEnabled(PluginBase.LOOP))
|
||||
return;
|
||||
|
||||
// Check if pump info is loaded
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package info.nightscout.androidaps.plugins.MDI;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui;
|
||||
|
||||
public class MDIFragment extends Fragment implements FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(MDIFragment.class);
|
||||
|
||||
private static MDIPlugin mdiPlugin = new MDIPlugin();
|
||||
|
||||
public static MDIPlugin getPlugin() {
|
||||
return mdiPlugin;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
package info.nightscout.androidaps.plugins.MDI;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class MDIPlugin implements PluginBase, PumpInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(MDIPlugin.class);
|
||||
|
||||
boolean fragmentEnabled = false;
|
||||
boolean fragmentVisible = false;
|
||||
|
||||
PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
public MDIPlugin() {
|
||||
pumpDescription.isBolusCapable = true;
|
||||
pumpDescription.bolusStep = 0.5d;
|
||||
|
||||
pumpDescription.isExtendedBolusCapable = false;
|
||||
pumpDescription.extendedBolusStep = 0d;
|
||||
|
||||
pumpDescription.isTempBasalCapable = false;
|
||||
pumpDescription.lowTempBasalStyle = PumpDescription.NONE;
|
||||
pumpDescription.highTempBasalStyle = PumpDescription.NONE;
|
||||
pumpDescription.maxHighTempPercent = 0;
|
||||
pumpDescription.maxHighTempAbsolute = 0;
|
||||
pumpDescription.lowTempPercentStep = 0;
|
||||
pumpDescription.lowTempAbsoluteStep = 0;
|
||||
pumpDescription.lowTempPercentDuration = 0;
|
||||
pumpDescription.lowTempAbsoluteDuration = 0;
|
||||
pumpDescription.highTempPercentStep = 0;
|
||||
pumpDescription.highTempAbsoluteStep = 0d;
|
||||
pumpDescription.highTempPercentDuration = 0;
|
||||
pumpDescription.highTempAbsoluteDuration = 0;
|
||||
|
||||
pumpDescription.isSetBasalProfileCapable = true;
|
||||
pumpDescription.basalStep = 0d;
|
||||
pumpDescription.basalMinimumRate = 0d;
|
||||
|
||||
pumpDescription.isRefillingCapable = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return MDIFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.mdi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == PUMP && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == PUMP) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == PUMP) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.PUMP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExtendedBoluslInProgress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setNewBasalProfile(NSProfile profile) {
|
||||
// Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThisProfileSet(NSProfile profile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return 0d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTempBasalAbsoluteRate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getTempBasal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getExtendedBolus() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTempBasalRemainingMinutes() {
|
||||
return 0d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getTempBasal(Date time) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = true;
|
||||
result.bolusDelivered = insulin;
|
||||
result.carbsDelivered = carbs;
|
||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopBolusDelivering() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.pumperror);
|
||||
if (Config.logPumpComm)
|
||||
log.debug("Setting temp basal absolute: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.pumperror);
|
||||
if (Config.logPumpComm)
|
||||
log.debug("Settings temp basal percent: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.pumperror);
|
||||
if (Config.logPumpComm)
|
||||
log.debug("Setting extended bolus: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelTempBasal() {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.pumperror);
|
||||
if (Config.logPumpComm)
|
||||
log.debug("Cancel temp basal: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelExtendedBolus() {
|
||||
PumpEnactResult result = new PumpEnactResult();
|
||||
result.success = false;
|
||||
result.comment = MainApp.instance().getString(R.string.pumperror);
|
||||
if (Config.logPumpComm)
|
||||
log.debug("Canceling extended basal: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getJSONStatus() {
|
||||
JSONObject pump = new JSONObject();
|
||||
JSONObject status = new JSONObject();
|
||||
JSONObject extended = new JSONObject();
|
||||
try {
|
||||
status.put("status", "normal");
|
||||
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
||||
try {
|
||||
extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
status.put("timestamp", DateUtil.toISOString(new Date()));
|
||||
|
||||
pump.put("status", status);
|
||||
pump.put("extended", extended);
|
||||
pump.put("clock", DateUtil.toISOString(new Date()));
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
return pump;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceID() {
|
||||
return "MDI";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpDescription getPumpDescription() {
|
||||
return pumpDescription;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.MM640g;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
public class MM640gFragment extends Fragment implements FragmentBase {
|
||||
|
||||
private static MM640gPlugin mm640gPlugin = new MM640gPlugin();
|
||||
|
||||
public static MM640gPlugin getPlugin() {
|
||||
return mm640gPlugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.mm640g_fragment, container, false);
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.MM640g;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class MM640gPlugin implements PluginBase, PumpInterface, BgSourceInterface {
|
||||
|
||||
boolean fragmentPumpEnabled = false;
|
||||
boolean fragmentProfileEnabled = false;
|
||||
boolean fragmentBgSourceEnabled = false;
|
||||
boolean fragmentPumpVisible = true;
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return MM640gFragment.class.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin base interface
|
||||
*/
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.PUMP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.mm640g);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled;
|
||||
else if (type == PluginBase.BGSOURCE) return fragmentBgSourceEnabled;
|
||||
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
|
||||
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
||||
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == PluginBase.PROFILE) this.fragmentProfileEnabled = fragmentEnabled;
|
||||
if (type == PluginBase.BGSOURCE) this.fragmentBgSourceEnabled = fragmentEnabled;
|
||||
else if (type == PluginBase.PUMP) this.fragmentPumpEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == PluginBase.PUMP)
|
||||
this.fragmentPumpVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin communications
|
||||
*/
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventPreferenceChange s) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Pump Interface
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTempBasalInProgress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExtendedBoluslInProgress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNewBasalProfile(NSProfile profile) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseBasalRate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTempBasalAbsoluteRate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTempBasalRemainingMinutes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getTempBasal(Date time) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getTempBasal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TempBasal getExtendedBolus() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) {
|
||||
return new PumpEnactResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopBolusDelivering() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) {
|
||||
return new PumpEnactResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) {
|
||||
return new PumpEnactResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
||||
return new PumpEnactResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelTempBasal() {
|
||||
return new PumpEnactResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpEnactResult cancelExtendedBolus() {
|
||||
return new PumpEnactResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getJSONStatus() {
|
||||
return new JSONObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceID() {
|
||||
return "MM640G"; // TODO: probably serial goes here
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.NSProfileViewer;
|
||||
package info.nightscout.androidaps.plugins.NSProfile;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
@ -13,14 +13,14 @@ import com.squareup.otto.Subscribe;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.NSProfileViewer.events.EventNSProfileViewerUpdateGUI;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.events.EventNSProfileUpdateGUI;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
||||
public class NSProfileViewerFragment extends Fragment implements FragmentBase {
|
||||
private static NSProfileViewerPlugin nsProfileViewerPlugin = new NSProfileViewerPlugin();
|
||||
public class NSProfileFragment extends Fragment implements FragmentBase {
|
||||
private static NSProfilePlugin nsProfilePlugin = new NSProfilePlugin();
|
||||
|
||||
public static NSProfileViewerPlugin getPlugin() {
|
||||
return nsProfileViewerPlugin;
|
||||
public static NSProfilePlugin getPlugin() {
|
||||
return nsProfilePlugin;
|
||||
}
|
||||
|
||||
private static TextView noProfile;
|
||||
|
@ -63,7 +63,7 @@ public class NSProfileViewerFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventNSProfileViewerUpdateGUI ev) {
|
||||
public void onStatusEvent(final EventNSProfileUpdateGUI ev) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
|
@ -75,19 +75,19 @@ public class NSProfileViewerFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
|
||||
private void updateGUI() {
|
||||
if (nsProfileViewerPlugin.profile == null) {
|
||||
if (nsProfilePlugin.profile == null) {
|
||||
noProfile.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
} else {
|
||||
noProfile.setVisibility(View.GONE);
|
||||
}
|
||||
units.setText(nsProfileViewerPlugin.profile.getUnits());
|
||||
dia.setText(DecimalFormatter.to2Decimal(nsProfileViewerPlugin.profile.getDia()) + " h");
|
||||
activeProfile.setText(nsProfileViewerPlugin.profile.getActiveProfile());
|
||||
ic.setText(nsProfileViewerPlugin.profile.getIcList());
|
||||
isf.setText(nsProfileViewerPlugin.profile.getIsfList());
|
||||
basal.setText(nsProfileViewerPlugin.profile.getBasalList());
|
||||
target.setText(nsProfileViewerPlugin.profile.getTargetList());
|
||||
units.setText(nsProfilePlugin.profile.getUnits());
|
||||
dia.setText(DecimalFormatter.to2Decimal(nsProfilePlugin.profile.getDia()) + " h");
|
||||
activeProfile.setText(nsProfilePlugin.profile.getActiveProfile());
|
||||
ic.setText(nsProfilePlugin.profile.getIcList());
|
||||
isf.setText(nsProfilePlugin.profile.getIsfList());
|
||||
basal.setText(nsProfilePlugin.profile.getBasalList());
|
||||
target.setText(nsProfilePlugin.profile.getTargetList());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.NSProfileViewer;
|
||||
package info.nightscout.androidaps.plugins.NSProfile;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -19,18 +19,18 @@ import info.nightscout.androidaps.Services.Intents;
|
|||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.plugins.NSProfileViewer.events.EventNSProfileViewerUpdateGUI;
|
||||
import info.nightscout.androidaps.plugins.NSProfile.events.EventNSProfileUpdateGUI;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class NSProfileViewerPlugin implements PluginBase, ProfileInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(NSProfileViewerPlugin.class);
|
||||
public class NSProfilePlugin implements PluginBase, ProfileInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(NSProfilePlugin.class);
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return NSProfileViewerFragment.class.getName();
|
||||
return NSProfileFragment.class.getName();
|
||||
}
|
||||
|
||||
static boolean fragmentEnabled = true;
|
||||
|
@ -38,7 +38,7 @@ public class NSProfileViewerPlugin implements PluginBase, ProfileInterface {
|
|||
|
||||
static NSProfile profile = null;
|
||||
|
||||
public NSProfileViewerPlugin() {
|
||||
public NSProfilePlugin() {
|
||||
MainApp.bus().register(this);
|
||||
loadNSProfile();
|
||||
|
||||
|
@ -51,12 +51,12 @@ public class NSProfileViewerPlugin implements PluginBase, ProfileInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == PROFILE && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,12 +66,12 @@ public class NSProfileViewerPlugin implements PluginBase, ProfileInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == PROFILE) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == PROFILE) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,7 +83,7 @@ public class NSProfileViewerPlugin implements PluginBase, ProfileInterface {
|
|||
public void onStatusEvent(final EventNewBasalProfile ev) {
|
||||
profile = new NSProfile(ev.newNSProfile.getData(), ev.newNSProfile.getActiveProfile());
|
||||
storeNSProfile();
|
||||
MainApp.bus().post(new EventNSProfileViewerUpdateGUI());
|
||||
MainApp.bus().post(new EventNSProfileUpdateGUI());
|
||||
}
|
||||
|
||||
private void storeNSProfile() {
|
|
@ -0,0 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.NSProfile.events;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class EventNSProfileUpdateGUI {
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.NSProfileViewer.events;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class EventNSProfileViewerUpdateGUI {
|
||||
}
|
|
@ -29,9 +29,12 @@ import info.nightscout.androidaps.interfaces.FragmentBase;
|
|||
public class ObjectivesFragment extends Fragment implements View.OnClickListener, FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
|
||||
|
||||
private static ObjectivesPlugin objectivesPlugin = new ObjectivesPlugin();
|
||||
private static ObjectivesPlugin objectivesPlugin;
|
||||
|
||||
public static ObjectivesPlugin getPlugin() {
|
||||
if (objectivesPlugin == null) {
|
||||
objectivesPlugin = new ObjectivesPlugin();
|
||||
}
|
||||
return objectivesPlugin;
|
||||
}
|
||||
|
||||
|
@ -67,7 +70,7 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener
|
|||
@Override
|
||||
public void onBindViewHolder(ObjectiveViewHolder holder, int position) {
|
||||
ObjectivesPlugin.Objective o = objectives.get(position);
|
||||
ObjectivesPlugin.RequirementResult requirementsMet = objectivesPlugin.requirementsMet(position);
|
||||
ObjectivesPlugin.RequirementResult requirementsMet = getPlugin().requirementsMet(position);
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
holder.position.setText(String.valueOf(position + 1));
|
||||
holder.objective.setText(o.objective);
|
||||
|
@ -91,7 +94,7 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener
|
|||
holder.verifyButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag();
|
||||
if (objectivesPlugin.requirementsMet(o.num).done || enableFake.isChecked()) {
|
||||
if (getPlugin().requirementsMet(o.num).done || enableFake.isChecked()) {
|
||||
o.accomplished = new Date();
|
||||
updateGUI();
|
||||
ObjectivesPlugin.saveProgress();
|
||||
|
@ -197,26 +200,26 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener
|
|||
});
|
||||
reset.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
objectivesPlugin.initializeData();
|
||||
objectivesPlugin.saveProgress();
|
||||
getPlugin().initializeData();
|
||||
getPlugin().saveProgress();
|
||||
updateGUI();
|
||||
}
|
||||
});
|
||||
|
||||
// Add correct translations to array after app is initialized
|
||||
objectivesPlugin.objectives.get(0).objective = MainApp.sResources.getString(R.string.objectives_0_objective);
|
||||
objectivesPlugin.objectives.get(1).objective = MainApp.sResources.getString(R.string.objectives_1_objective);
|
||||
objectivesPlugin.objectives.get(2).objective = MainApp.sResources.getString(R.string.objectives_2_objective);
|
||||
objectivesPlugin.objectives.get(3).objective = MainApp.sResources.getString(R.string.objectives_3_objective);
|
||||
objectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective);
|
||||
objectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
|
||||
objectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
|
||||
objectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
|
||||
objectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
|
||||
objectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
|
||||
objectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate);
|
||||
objectivesPlugin.objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate);
|
||||
objectivesPlugin.objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
|
||||
getPlugin().objectives.get(0).objective = MainApp.sResources.getString(R.string.objectives_0_objective);
|
||||
getPlugin().objectives.get(1).objective = MainApp.sResources.getString(R.string.objectives_1_objective);
|
||||
getPlugin().objectives.get(2).objective = MainApp.sResources.getString(R.string.objectives_2_objective);
|
||||
getPlugin().objectives.get(3).objective = MainApp.sResources.getString(R.string.objectives_3_objective);
|
||||
getPlugin().objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective);
|
||||
getPlugin().objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
|
||||
getPlugin().objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
|
||||
getPlugin().objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
|
||||
getPlugin().objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
|
||||
getPlugin().objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
|
||||
getPlugin().objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate);
|
||||
getPlugin().objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate);
|
||||
getPlugin().objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
|
||||
updateGUI();
|
||||
|
||||
return view;
|
||||
|
|
|
@ -51,13 +51,13 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return true;
|
||||
return type == CONSTRAINTS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class);
|
||||
return fragmentVisible && loopPlugin != null && loopPlugin.isVisibleInTabs(type);
|
||||
return type == CONSTRAINTS && fragmentVisible && loopPlugin != null && loopPlugin.isVisibleInTabs(LOOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +71,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == CONSTRAINTS) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
public class Objective {
|
||||
|
|
|
@ -24,9 +24,12 @@ import info.nightscout.utils.JSONFormatter;
|
|||
public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, FragmentBase {
|
||||
private static Logger log = LoggerFactory.getLogger(OpenAPSMAFragment.class);
|
||||
|
||||
private static OpenAPSMAPlugin openAPSMAPlugin = new OpenAPSMAPlugin();
|
||||
private static OpenAPSMAPlugin openAPSMAPlugin;
|
||||
|
||||
public static OpenAPSMAPlugin getPlugin() {
|
||||
if(openAPSMAPlugin==null){
|
||||
openAPSMAPlugin = new OpenAPSMAPlugin();
|
||||
}
|
||||
return openAPSMAPlugin;
|
||||
}
|
||||
|
||||
|
@ -64,7 +67,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
|
|||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.openapsma_run:
|
||||
openAPSMAPlugin.invoke();
|
||||
getPlugin().invoke();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -98,15 +101,15 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener,
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (openAPSMAPlugin.lastAPSResult != null) {
|
||||
glucoseStatusView.setText(JSONFormatter.format(openAPSMAPlugin.lastDetermineBasalAdapterJS.getGlucoseStatusParam()));
|
||||
currentTempView.setText(JSONFormatter.format(openAPSMAPlugin.lastDetermineBasalAdapterJS.getCurrentTempParam()));
|
||||
iobDataView.setText(JSONFormatter.format(openAPSMAPlugin.lastDetermineBasalAdapterJS.getIobDataParam()));
|
||||
profileView.setText(JSONFormatter.format(openAPSMAPlugin.lastDetermineBasalAdapterJS.getProfileParam()));
|
||||
mealDataView.setText(JSONFormatter.format(openAPSMAPlugin.lastDetermineBasalAdapterJS.getMealDataParam()));
|
||||
resultView.setText(JSONFormatter.format(openAPSMAPlugin.lastAPSResult.json));
|
||||
requestView.setText(openAPSMAPlugin.lastAPSResult.toSpanned());
|
||||
lastRunView.setText(openAPSMAPlugin.lastAPSRun.toLocaleString());
|
||||
if (getPlugin().lastAPSResult != null) {
|
||||
glucoseStatusView.setText(JSONFormatter.format(getPlugin().lastDetermineBasalAdapterJS.getGlucoseStatusParam()));
|
||||
currentTempView.setText(JSONFormatter.format(getPlugin().lastDetermineBasalAdapterJS.getCurrentTempParam()));
|
||||
iobDataView.setText(JSONFormatter.format(getPlugin().lastDetermineBasalAdapterJS.getIobDataParam()));
|
||||
profileView.setText(JSONFormatter.format(getPlugin().lastDetermineBasalAdapterJS.getProfileParam()));
|
||||
mealDataView.setText(JSONFormatter.format(getPlugin().lastDetermineBasalAdapterJS.getMealDataParam()));
|
||||
resultView.setText(JSONFormatter.format(getPlugin().lastAPSResult.json));
|
||||
requestView.setText(getPlugin().lastAPSResult.toSpanned());
|
||||
lastRunView.setText(getPlugin().lastAPSRun.toLocaleString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -58,12 +58,12 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,12 +73,12 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == APS) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == APS) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,6 +103,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
|
||||
@Override
|
||||
public void invoke() {
|
||||
lastAPSResult = null;
|
||||
DetermineBasalAdapterJS determineBasalAdapterJS = null;
|
||||
try {
|
||||
determineBasalAdapterJS = new DetermineBasalAdapterJS(new ScriptReader(MainApp.instance().getBaseContext()));
|
||||
|
@ -234,7 +235,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
if (value < lowLimit || value > highLimit) {
|
||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), valueName);
|
||||
log.error(msg);
|
||||
sendErrorToNSClient(msg);
|
||||
MainApp.getConfigBuilder().uploadError(msg);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
||||
value = Math.max(value, lowLimit);
|
||||
value = Math.min(value, highLimit);
|
||||
|
@ -242,26 +243,4 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static void sendErrorToNSClient(String error) {
|
||||
Context context = MainApp.instance().getApplicationContext();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("action", "dbAdd");
|
||||
bundle.putString("collection", "treatments");
|
||||
JSONObject data = new JSONObject();
|
||||
try {
|
||||
data.put("eventType", "Announcement");
|
||||
data.put("created_at", DateUtil.toISOString(new Date()));
|
||||
data.put("notes", error);
|
||||
data.put("isAnnouncement", true);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
bundle.putString("data", data.toString());
|
||||
Intent intent = new Intent(Intents.ACTION_DATABASE);
|
||||
intent.putExtras(bundle);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
context.sendBroadcast(intent);
|
||||
DbLogger.dbAdd(intent, data.toString(), OpenAPSMAPlugin.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -380,7 +380,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener {
|
|||
correctionInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCorrection) + "U");
|
||||
calculatedTotalInsulin = wizard.calculatedTotalInsulin;
|
||||
|
||||
if (calculatedTotalInsulin < 0) {
|
||||
if (calculatedTotalInsulin <= 0) {
|
||||
total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
|
||||
totalInsulin.setText("");
|
||||
} else {
|
||||
|
|
|
@ -12,9 +12,45 @@ public class Notification {
|
|||
public static final int LOW = 2;
|
||||
public static final int INFO = 3;
|
||||
|
||||
public static final int PROFILE_SET_FAILED = 0;
|
||||
public static final int PROFILE_SET_OK = 1;
|
||||
public static final int EASYMODE_ENABLED = 2;
|
||||
public static final int EXTENDED_BOLUS_DISABLED = 3;
|
||||
public static final int UD_MODE_ENABLED = 4;
|
||||
public static final int PROFILE_NOT_SET_NOT_INITIALIZED = 5;
|
||||
public static final int FAILED_UDPATE_PROFILE = 6;
|
||||
public static final int BASAL_VALUE_BELOW_MINIMUM = 7;
|
||||
|
||||
public int id;
|
||||
Date date;
|
||||
String text;
|
||||
Date validTo = new Date(0);
|
||||
int level;
|
||||
public Date date;
|
||||
public String text;
|
||||
public int level;
|
||||
public Date validTo = new Date(0);
|
||||
|
||||
public Notification() {
|
||||
}
|
||||
|
||||
public Notification(int id, Date date, String text, int level, Date validTo) {
|
||||
this.id = id;
|
||||
this.date = date;
|
||||
this.text = text;
|
||||
this.level = level;
|
||||
this.validTo = validTo;
|
||||
}
|
||||
|
||||
public Notification(int id, String text, int level, int validMinutes) {
|
||||
this.id = id;
|
||||
this.date = new Date();
|
||||
this.text = text;
|
||||
this.level = level;
|
||||
this.validTo = new Date(new Date().getTime() + validMinutes * 60 * 1000L);
|
||||
}
|
||||
|
||||
public Notification(int id, String text, int level) {
|
||||
this.id = id;
|
||||
this.date = new Date();
|
||||
this.text = text;
|
||||
this.level = level;
|
||||
this.validTo = new Date(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package info.nightscout.androidaps.plugins.Overview;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -12,6 +15,7 @@ import java.util.List;
|
|||
*/
|
||||
|
||||
public class NotificationStore {
|
||||
private static Logger log = LoggerFactory.getLogger(NotificationStore.class);
|
||||
public List<Notification> store = new ArrayList<Notification>();
|
||||
|
||||
public NotificationStore() {
|
||||
|
@ -29,6 +33,7 @@ public class NotificationStore {
|
|||
}
|
||||
|
||||
public void add(Notification n) {
|
||||
log.info("Notification received: " + n.text);
|
||||
for (int i = 0; i < store.size(); i++) {
|
||||
if (get(i).id == n.id) {
|
||||
get(i).date = n.date;
|
||||
|
@ -54,6 +59,7 @@ public class NotificationStore {
|
|||
Notification n = get(i);
|
||||
if (n.validTo.getTime() != 0 && n.validTo.getTime() < new Date().getTime()) {
|
||||
store.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import info.nightscout.androidaps.db.BgReading;
|
|||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
|
@ -95,6 +96,7 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
|
||||
TextView bgView;
|
||||
TextView arrowView;
|
||||
TextView timeAgoView;
|
||||
TextView deltaView;
|
||||
TextView runningTempView;
|
||||
|
@ -138,6 +140,7 @@ public class OverviewFragment extends Fragment {
|
|||
|
||||
View view = inflater.inflate(R.layout.overview_fragment, container, false);
|
||||
bgView = (TextView) view.findViewById(R.id.overview_bg);
|
||||
arrowView = (TextView) view.findViewById(R.id.overview_arrow);
|
||||
timeAgoView = (TextView) view.findViewById(R.id.overview_timeago);
|
||||
deltaView = (TextView) view.findViewById(R.id.overview_delta);
|
||||
runningTempView = (TextView) view.findViewById(R.id.overview_runningtemp);
|
||||
|
@ -364,6 +367,11 @@ public class OverviewFragment extends Fragment {
|
|||
updateGUIIfVisible();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventInitializationChanged ev) {
|
||||
updateGUIIfVisible();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventPreferenceChange ev) {
|
||||
updateGUIIfVisible();
|
||||
|
@ -442,7 +450,7 @@ public class OverviewFragment extends Fragment {
|
|||
|
||||
// open loop mode
|
||||
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
|
||||
if (Config.APS) {
|
||||
if (Config.APS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable) {
|
||||
apsModeView.setVisibility(View.VISIBLE);
|
||||
apsModeView.setBackgroundResource(R.drawable.loopmodeborder);
|
||||
apsModeView.setTextColor(Color.BLACK);
|
||||
|
@ -486,22 +494,22 @@ public class OverviewFragment extends Fragment {
|
|||
apsModeView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// **** Temp button ****
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
|
||||
showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist
|
||||
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
|
||||
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.changeRequested; // change is requested
|
||||
|
||||
if (showAcceptButton) {
|
||||
if (showAcceptButton && pump.isInitialized()) {
|
||||
acceptTempLayout.setVisibility(View.VISIBLE);
|
||||
acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
|
||||
} else {
|
||||
acceptTempLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// **** Temp button ****
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
if (pump.isTempBasalInProgress()) {
|
||||
TempBasal activeTemp = pump.getTempBasal();
|
||||
cancelTempLayout.setVisibility(View.VISIBLE);
|
||||
|
@ -531,7 +539,7 @@ public class OverviewFragment extends Fragment {
|
|||
});
|
||||
activeProfileView.setLongClickable(true);
|
||||
|
||||
if (profile == null) {
|
||||
if (profile == null || !pump.isInitialized()) {
|
||||
// disable all treatment buttons because we are not able to check constraints without profile
|
||||
wizardButton.setVisibility(View.INVISIBLE);
|
||||
treatmentButton.setVisibility(View.INVISIBLE);
|
||||
|
@ -545,7 +553,7 @@ public class OverviewFragment extends Fragment {
|
|||
|
||||
// QuickWizard button
|
||||
QuickWizard.QuickWizardEntry quickWizardEntry = getPlugin().quickWizard.getActive();
|
||||
if (quickWizardEntry != null && lastBG != null) {
|
||||
if (quickWizardEntry != null && lastBG != null && pump.isInitialized()) {
|
||||
quickWizardLayout.setVisibility(View.VISIBLE);
|
||||
String text = MainApp.sResources.getString(R.string.bolus) + ": " + quickWizardEntry.buttonText() + " " + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g";
|
||||
BolusWizard wizard = new BolusWizard();
|
||||
|
@ -560,6 +568,7 @@ public class OverviewFragment extends Fragment {
|
|||
// **** BG value ****
|
||||
if (lastBG != null && bgView != null) {
|
||||
bgView.setText(lastBG.valueToUnitsToString(profile.getUnits()));
|
||||
arrowView.setText(lastBG.directionToSymbol());
|
||||
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
if (glucoseStatus != null)
|
||||
deltaView.setText("Δ " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
|
||||
|
@ -677,6 +686,13 @@ public class OverviewFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
bgGraph.getViewport().setMaxX(toTime);
|
||||
bgGraph.getViewport().setMinX(fromTime);
|
||||
bgGraph.getViewport().setXAxisBoundsManual(true);
|
||||
bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH"));
|
||||
bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space
|
||||
|
||||
// **** BG graph ****
|
||||
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getDataFromTime(fromTime);
|
||||
List<BgReading> inRangeArray = new ArrayList<BgReading>();
|
||||
|
@ -757,13 +773,6 @@ public class OverviewFragment extends Fragment {
|
|||
seriesTreatments.setColor(Color.CYAN);
|
||||
}
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
bgGraph.getViewport().setMaxX(toTime);
|
||||
bgGraph.getViewport().setMinX(fromTime);
|
||||
bgGraph.getViewport().setXAxisBoundsManual(true);
|
||||
bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH"));
|
||||
bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space
|
||||
|
||||
// set manual y bounds to have nice steps
|
||||
bgGraph.getViewport().setMaxY(maxBgValue);
|
||||
bgGraph.getViewport().setMinY(0);
|
||||
|
|
|
@ -49,7 +49,7 @@ public class OverviewPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return true;
|
||||
return type == GENERAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,7 +40,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return true;
|
||||
return type == CONSTRAINTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,7 +54,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int tyep, boolean fragmentEnabled) {
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
@Override
|
||||
public boolean isLoopEnabled() {
|
||||
return true;
|
||||
return MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.SimpleProfile;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
|
@ -8,14 +9,22 @@ import android.text.TextWatcher;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||
import info.nightscout.androidaps.interfaces.FragmentBase;
|
||||
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
||||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
||||
|
@ -36,6 +45,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
EditText basalView;
|
||||
EditText targetlowView;
|
||||
EditText targethighView;
|
||||
Button profileswitchButton;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -50,6 +60,9 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
basalView = (EditText) layout.findViewById(R.id.simpleprofile_basalrate);
|
||||
targetlowView = (EditText) layout.findViewById(R.id.simpleprofile_targetlow);
|
||||
targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh);
|
||||
profileswitchButton = (Button) layout.findViewById(R.id.simpleprofile_profileswitch);
|
||||
|
||||
onStatusEvent(null);
|
||||
|
||||
mgdlView.setChecked(simpleProfilePlugin.mgdl);
|
||||
mmolView.setChecked(simpleProfilePlugin.mmol);
|
||||
|
@ -80,6 +93,17 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
}
|
||||
});
|
||||
|
||||
profileswitchButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
||||
final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
|
||||
profileswitch.executeProfileSwitch = true;
|
||||
newDialog.setOptions(profileswitch);
|
||||
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
||||
}
|
||||
});
|
||||
|
||||
TextWatcher textWatch = new TextWatcher() {
|
||||
|
||||
@Override
|
||||
|
@ -115,4 +139,32 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
|
|||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MainApp.bus().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventInitializationChanged e) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!MainApp.getConfigBuilder().isInitialized()) {
|
||||
profileswitchButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
profileswitchButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,12 +60,12 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == PROFILE && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == PROFILE && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,12 +75,12 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == PROFILE) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == PROFILE) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
public void storeSettings() {
|
||||
|
|
|
@ -29,9 +29,13 @@ import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommuni
|
|||
public class SmsCommunicatorFragment extends Fragment {
|
||||
private static Logger log = LoggerFactory.getLogger(SmsCommunicatorFragment.class);
|
||||
|
||||
private static SmsCommunicatorPlugin smsCommunicatorPlugin = new SmsCommunicatorPlugin();
|
||||
private static SmsCommunicatorPlugin smsCommunicatorPlugin;
|
||||
|
||||
public static SmsCommunicatorPlugin getPlugin() {
|
||||
|
||||
if(smsCommunicatorPlugin==null){
|
||||
smsCommunicatorPlugin = new SmsCommunicatorPlugin();
|
||||
}
|
||||
return smsCommunicatorPlugin;
|
||||
}
|
||||
|
||||
|
@ -81,15 +85,15 @@ public class SmsCommunicatorFragment extends Fragment {
|
|||
return (int) (object1.date.getTime() - object2.date.getTime());
|
||||
}
|
||||
}
|
||||
Collections.sort(smsCommunicatorPlugin.messages, new CustomComparator());
|
||||
Collections.sort(getPlugin().messages, new CustomComparator());
|
||||
int messagesToShow = 40;
|
||||
|
||||
int start = Math.max(0, smsCommunicatorPlugin.messages.size() - messagesToShow);
|
||||
int start = Math.max(0, getPlugin().messages.size() - messagesToShow);
|
||||
DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||
|
||||
String logText = "";
|
||||
for (int x = start; x < smsCommunicatorPlugin.messages.size(); x++) {
|
||||
SmsCommunicatorPlugin.Sms sms = smsCommunicatorPlugin.messages.get(x);
|
||||
for (int x = start; x < getPlugin().messages.size(); x++) {
|
||||
SmsCommunicatorPlugin.Sms sms = getPlugin().messages.get(x);
|
||||
if (sms.received) {
|
||||
logText += df.format(sms.date) + " <<< " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " <b>" + sms.text + "</b><br>";
|
||||
} else if (sms.sent) {
|
||||
|
|
|
@ -16,18 +16,26 @@ import java.text.Normalizer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.Services.Intents;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
/**
|
||||
|
@ -41,6 +49,8 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
|
||||
final long CONFIRM_TIMEOUT = 5 * 60 * 1000L;
|
||||
|
||||
List<String> allowedNumbers = new ArrayList<String>();
|
||||
|
||||
public class Sms {
|
||||
String phoneNumber;
|
||||
String text;
|
||||
|
@ -67,6 +77,14 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
sent = true;
|
||||
}
|
||||
|
||||
public Sms(String phoneNumber, String text, Date date, String confirmCode) {
|
||||
this.phoneNumber = phoneNumber;
|
||||
this.text = text;
|
||||
this.date = date;
|
||||
this.confirmCode = confirmCode;
|
||||
sent = true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "SMS from " + phoneNumber + ": " + text;
|
||||
}
|
||||
|
@ -81,6 +99,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
|
||||
public SmsCommunicatorPlugin() {
|
||||
MainApp.bus().register(this);
|
||||
processSettings(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,12 +119,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,12 +134,34 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
SmsCommunicatorPlugin.fragmentEnabled = fragmentEnabled;
|
||||
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
SmsCommunicatorPlugin.fragmentVisible = fragmentVisible;
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void processSettings(final EventPreferenceChange ev) {
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
String settings = sharedPreferences.getString("smscommunicator_allowednumbers", "");
|
||||
|
||||
String pattern = ";";
|
||||
|
||||
String[] substrings = settings.split(pattern);
|
||||
for (String number : substrings) {
|
||||
String cleaned = number.replaceAll("\\s+", "");
|
||||
allowedNumbers.add(cleaned);
|
||||
log.debug("Found allowed number: " + cleaned);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAllowedNumber(String number) {
|
||||
for (String num : allowedNumbers) {
|
||||
if (num.equals(number)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -135,14 +176,13 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
private void processSms(Sms receivedSms) {
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
|
||||
if (!isEnabled(PluginBase.GENERAL)) {
|
||||
log.debug("Ignoring SMS. Plugin disabled.");
|
||||
return;
|
||||
}
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
String allowedNumbers = sharedPreferences.getString("smscommunicator_allowednumbers", "");
|
||||
|
||||
if (!allowedNumbers.contains(receivedSms.phoneNumber)) {
|
||||
if (!isAllowedNumber(receivedSms.phoneNumber)) {
|
||||
log.debug("Ignoring SMS from: " + receivedSms.phoneNumber + ". Sender not allowed");
|
||||
return;
|
||||
}
|
||||
|
@ -156,10 +196,42 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
Double amount = 0d;
|
||||
Double tempBasal = 0d;
|
||||
String passCode = "";
|
||||
Sms newSms = null;
|
||||
|
||||
if (splited.length > 0) {
|
||||
switch (splited[0].toUpperCase()) {
|
||||
case "BG":
|
||||
BgReading actualBG = MainApp.getDbHelper().actualBg();
|
||||
BgReading lastBG = MainApp.getDbHelper().lastBg();
|
||||
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
String units = profile.getUnits();
|
||||
|
||||
Long agoMsec = new Date().getTime() - lastBG.timeIndex;
|
||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||
|
||||
if (actualBG != null) {
|
||||
reply = MainApp.sResources.getString(R.string.actualbg) + " " + actualBG.valueToUnitsToString(units) + ", ";
|
||||
} else if (lastBG != null) {
|
||||
reply = MainApp.sResources.getString(R.string.lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + agoMin + MainApp.sResources.getString(R.string.minago) + ", ";
|
||||
}
|
||||
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
if (glucoseStatus != null)
|
||||
reply += MainApp.sResources.getString(R.string.delta) + ": " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", ";
|
||||
|
||||
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
|
||||
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
|
||||
if (bolusIob == null) bolusIob = new IobTotal();
|
||||
MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB();
|
||||
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
|
||||
if (basalIob == null) basalIob = new IobTotal();
|
||||
|
||||
reply += MainApp.sResources.getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
|
||||
+ MainApp.sResources.getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
|
||||
+ MainApp.sResources.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
|
||||
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
case "LOOP":
|
||||
switch (splited[1].toUpperCase()) {
|
||||
case "STOP":
|
||||
|
@ -167,7 +239,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) {
|
||||
loopPlugin.setFragmentEnabled(PluginBase.LOOP, false);
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled);
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
|
@ -176,7 +248,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
if (loopPlugin != null && !loopPlugin.isEnabled(PluginBase.LOOP)) {
|
||||
loopPlugin.setFragmentEnabled(PluginBase.LOOP, true);
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeenenabled);
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
|
@ -188,7 +260,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_loopisdisabled);
|
||||
}
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
|
@ -202,7 +274,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
|
||||
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0);
|
||||
reply = "TERATMENTS REFRESH " + q.size() + " receivers";
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
}
|
||||
|
@ -214,16 +286,22 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
|
||||
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0);
|
||||
reply = "NSCLIENT RESTART " + q.size() + " receivers";
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "DANAR":
|
||||
DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
|
||||
if (danaRPlugin != null && danaRPlugin.isEnabled(PluginBase.PUMP))
|
||||
if (danaRPlugin != null && danaRPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
reply = danaRPlugin.shortStatus();
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
if (danaRKoreanPlugin != null && danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
reply = danaRKoreanPlugin.shortStatus();
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
receivedSms.processed = true;
|
||||
break;
|
||||
case "BASAL":
|
||||
|
@ -234,13 +312,11 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
passCode = generatePasscode();
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_basalstopreplywithcode), passCode);
|
||||
receivedSms.processed = true;
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
newSms.confirmCode = passCode;
|
||||
resetWaitingMessages();
|
||||
cancelTempBasalWaitingForConfirmation = newSms;
|
||||
sendSMS(cancelTempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.remotebasalnotallowed);
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
} else {
|
||||
tempBasal = SafeParse.stringToDouble(splited[1]);
|
||||
|
@ -249,14 +325,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
passCode = generatePasscode();
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_basalreplywithcode), tempBasal, passCode);
|
||||
receivedSms.processed = true;
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
newSms.tempBasal = tempBasal;
|
||||
newSms.confirmCode = passCode;
|
||||
resetWaitingMessages();
|
||||
tempBasalWaitingForConfirmation = newSms;
|
||||
sendSMS(tempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
|
||||
tempBasalWaitingForConfirmation.tempBasal = tempBasal;
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.remotebasalnotallowed);
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +338,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
case "BOLUS":
|
||||
if (new Date().getTime() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) {
|
||||
reply = MainApp.sResources.getString(R.string.remotebolusnotallowed);
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else if (splited.length > 1) {
|
||||
amount = SafeParse.stringToDouble(splited[1]);
|
||||
amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
|
||||
|
@ -273,14 +347,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
passCode = generatePasscode();
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusreplywithcode), amount, passCode);
|
||||
receivedSms.processed = true;
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
newSms.bolusRequested = amount;
|
||||
newSms.confirmCode = passCode;
|
||||
resetWaitingMessages();
|
||||
bolusWaitingForConfirmation = newSms;
|
||||
sendSMS(bolusWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
|
||||
bolusWaitingForConfirmation.bolusRequested = amount;
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.remotebolusnotallowed);
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -296,11 +368,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
reply = String.format(MainApp.sResources.getString(R.string.bolusdelivered), result.bolusDelivered);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
lastRemoteBolusTime = new Date();
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.bolusfailed);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
}
|
||||
} else if (tempBasalWaitingForConfirmation != null && !tempBasalWaitingForConfirmation.processed &&
|
||||
tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - tempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) {
|
||||
|
@ -312,11 +385,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
if (result.success) {
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
}
|
||||
} else if (cancelTempBasalWaitingForConfirmation != null && !cancelTempBasalWaitingForConfirmation.processed &&
|
||||
cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - cancelTempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) {
|
||||
|
@ -328,30 +402,46 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
if (result.success) {
|
||||
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled));
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
} else {
|
||||
reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcancelfailed);
|
||||
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
|
||||
}
|
||||
newSms = new Sms(receivedSms.phoneNumber, reply, new Date());
|
||||
}
|
||||
} else {
|
||||
newSms = new Sms(receivedSms.phoneNumber, MainApp.sResources.getString(R.string.smscommunicator_unknowncommand), new Date());
|
||||
sendSMS(new Sms(receivedSms.phoneNumber, MainApp.sResources.getString(R.string.smscommunicator_unknowncommand), new Date()));
|
||||
}
|
||||
resetWaitingMessages();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (newSms != null) {
|
||||
SmsManager smsManager = SmsManager.getDefault();
|
||||
newSms.text = stripAccents(newSms.text);
|
||||
if (newSms.text.length() > 140) newSms.text = newSms.text.substring(0, 139);
|
||||
smsManager.sendTextMessage(newSms.phoneNumber, null, newSms.text, null, null);
|
||||
messages.add(newSms);
|
||||
}
|
||||
MainApp.bus().post(new EventSmsCommunicatorUpdateGui());
|
||||
}
|
||||
|
||||
public void sendNotificationToAllNumbers(String text) {
|
||||
for (int i = 0; i < allowedNumbers.size(); i++) {
|
||||
Sms sms = new Sms(allowedNumbers.get(i), text, new Date());
|
||||
sendSMS(sms);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSMSToAllNumbers(Sms sms) {
|
||||
for (int i = 0; i < allowedNumbers.size(); i++) {
|
||||
sms.phoneNumber = allowedNumbers.get(i);
|
||||
sendSMS(sms);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSMS(Sms sms) {
|
||||
SmsManager smsManager = SmsManager.getDefault();
|
||||
sms.text = stripAccents(sms.text);
|
||||
if (sms.text.length() > 140) sms.text = sms.text.substring(0, 139);
|
||||
smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null);
|
||||
messages.add(sms);
|
||||
}
|
||||
|
||||
private String generatePasscode() {
|
||||
int startChar1 = 'A'; // on iphone 1st char is uppercase :)
|
||||
String passCode = Character.toString((char) (startChar1 + Math.random() * ('z' - 'a' + 1)));
|
||||
|
|
|
@ -28,7 +28,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == BGSOURCE && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,7 +43,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,7 +30,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == BGSOURCE && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,7 +45,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
SourceXdripPlugin.fragmentEnabled = fragmentEnabled;
|
||||
if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -66,12 +66,12 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == TEMPBASAL && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == TEMPBASAL && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,12 +81,12 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == TEMPBASAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == TEMPBASAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,12 +49,12 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == TREATMENT && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == TREATMENT && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,12 +64,12 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == TREATMENT) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == TREATMENT) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@ import info.nightscout.androidaps.R;
|
|||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.db.TempBasal;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||
import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui;
|
||||
|
@ -37,6 +38,36 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
boolean fragmentEnabled = true;
|
||||
boolean fragmentVisible = true;
|
||||
|
||||
PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
public VirtualPumpPlugin() {
|
||||
pumpDescription.isBolusCapable = true;
|
||||
pumpDescription.bolusStep = 1d;
|
||||
|
||||
pumpDescription.isExtendedBolusCapable = true;
|
||||
pumpDescription.extendedBolusStep = 0.2d;
|
||||
|
||||
pumpDescription.isTempBasalCapable = true;
|
||||
pumpDescription.lowTempBasalStyle = PumpDescription.ABSOLUTE | PumpDescription.PERCENT;
|
||||
pumpDescription.highTempBasalStyle = PumpDescription.ABSOLUTE | PumpDescription.PERCENT;
|
||||
pumpDescription.maxHighTempPercent = 600;
|
||||
pumpDescription.maxHighTempAbsolute = 10;
|
||||
pumpDescription.lowTempPercentStep = 5;
|
||||
pumpDescription.lowTempAbsoluteStep = 0.1;
|
||||
pumpDescription.lowTempPercentDuration = 30;
|
||||
pumpDescription.lowTempAbsoluteDuration = 30;
|
||||
pumpDescription.highTempPercentStep = 10;
|
||||
pumpDescription.highTempAbsoluteStep = 0.05d;
|
||||
pumpDescription.highTempPercentDuration = 30;
|
||||
pumpDescription.highTempAbsoluteDuration = 30;
|
||||
|
||||
pumpDescription.isSetBasalProfileCapable = true;
|
||||
pumpDescription.basalStep = 0.01d;
|
||||
pumpDescription.basalMinimumRate = 0.04d;
|
||||
|
||||
pumpDescription.isRefillingCapable = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return VirtualPumpFragment.class.getName();
|
||||
|
@ -49,12 +80,12 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == PUMP && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == PUMP && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,12 +95,12 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (type == PUMP) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
this.fragmentVisible = fragmentVisible;
|
||||
if (type == PUMP) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,8 +124,14 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setNewBasalProfile(NSProfile profile) {
|
||||
public int setNewBasalProfile(NSProfile profile) {
|
||||
// Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThisProfileSet(NSProfile profile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -367,4 +404,9 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
return "VirtualPump";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PumpDescription getPumpDescription() {
|
||||
return pumpDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class WearPlugin implements PluginBase {
|
|||
private static WatchUpdaterService watchUS;
|
||||
private final Context ctx;
|
||||
|
||||
WearPlugin(Context ctx){
|
||||
WearPlugin(Context ctx) {
|
||||
this.ctx = ctx;
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
@ -50,12 +50,12 @@ public class WearPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return fragmentEnabled;
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return fragmentVisible;
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,39 +65,41 @@ public class WearPlugin implements PluginBase {
|
|||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
WearPlugin.fragmentEnabled = fragmentEnabled;
|
||||
if(watchUS!=null){
|
||||
if (type == GENERAL) {
|
||||
this.fragmentEnabled = fragmentEnabled;
|
||||
if (watchUS != null) {
|
||||
watchUS.setSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
WearPlugin.fragmentVisible = fragmentVisible;
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
private void sendDataToWatch(boolean status, boolean basals, boolean bgValue){
|
||||
private void sendDataToWatch(boolean status, boolean basals, boolean bgValue) {
|
||||
if (isEnabled(getType())) { //only start service when this plugin is enabled
|
||||
|
||||
if(bgValue){
|
||||
if (bgValue) {
|
||||
ctx.startService(new Intent(ctx, WatchUpdaterService.class));
|
||||
}
|
||||
|
||||
if(basals){
|
||||
if (basals) {
|
||||
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BASALS));
|
||||
}
|
||||
|
||||
if(status){
|
||||
if (status) {
|
||||
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_STATUS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resendDataToWatch(){
|
||||
void resendDataToWatch() {
|
||||
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_RESEND));
|
||||
}
|
||||
|
||||
void openSettings(){
|
||||
void openSettings() {
|
||||
ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS));
|
||||
}
|
||||
|
||||
|
@ -132,11 +134,11 @@ public class WearPlugin implements PluginBase {
|
|||
return fragmentEnabled;
|
||||
}
|
||||
|
||||
public static void registerWatchUpdaterService(WatchUpdaterService wus){
|
||||
public static void registerWatchUpdaterService(WatchUpdaterService wus) {
|
||||
watchUS = wus;
|
||||
}
|
||||
|
||||
public static void unRegisterWatchUpdaterService(){
|
||||
public static void unRegisterWatchUpdaterService() {
|
||||
watchUS = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import info.nightscout.androidaps.interfaces.PluginBase;
|
|||
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
|
||||
import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService;
|
||||
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class KeepAliveReceiver extends BroadcastReceiver {
|
||||
|
@ -51,6 +52,18 @@ public class KeepAliveReceiver extends BroadcastReceiver {
|
|||
t.start();
|
||||
}
|
||||
}
|
||||
final DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
if (danaRKoreanPlugin != null && Config.DANAR && danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
|
||||
if (danaRKoreanPlugin.getDanaRPump().lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime() && !danaRKoreanPlugin.isConnected() && !danaRKoreanPlugin.isConnecting()) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
danaRKoreanPlugin.doConnect("KeepAlive");
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
||||
wl.release();
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue