initial commit of openhab core components

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2015-12-26 23:22:23 +01:00
commit a5b86617a6
1010 changed files with 69152 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
**/target/
.metadata/
/*features*/*/src/main/history/
maven-metadata-local.xml
View File
+217
View File
@@ -0,0 +1,217 @@
# Contributing to openHAB
Want to hack on openHAB? Awesome! Here are instructions to get you
started. They are probably not perfect, please let us know if anything
feels wrong or incomplete.
## Reporting Issues
Please report [openHAB2 specific issues here](https://github.com/openhab/openhab2/issues), while issues that are related to the core framework should be reported in the [bugzilla of Eclipse SmartHome](https://bugs.eclipse.org/bugs/buglist.cgi?product=SmartHome&component=Core).
Do not worry, if you are not clear, which category your issue belongs to - we will redirect you, if necessary.
## Build Environment
For instructions on setting up your development environment, please
see our dedicated [IDE setup guide](https://github.com/openhab/openhab/wiki/IDE-Setup).
## Contribution guidelines
### Pull requests are always welcome
We are always thrilled to receive pull requests, and do our best to
process them as fast as possible. Not sure if that typo is worth a pull
request? Do it! We will appreciate it.
If your pull request is not accepted on the first try, don't be
discouraged! If there's a problem with the implementation, hopefully you
received feedback on what to improve.
We're trying very hard to keep openHAB lean and focused. We don't want it
to do everything for everybody. This means that we might decide against
incorporating a new feature. However, there might be a way to implement
that feature *on top of* openHAB.
### Discuss your design on the mailing list
We recommend discussing your plans [in the discussion forum](https://community.openhab.org/c/openhab-2)
before starting to code - especially for more ambitious contributions.
This gives other contributors a chance to point you in the right
direction, give feedback on your design, and maybe point out if someone
else is working on the same thing.
### Create issues...
Any significant improvement should be documented as [a GitHub
issue](https://github.com/openhab/openhab2/issues?labels=enhancement&page=1&state=open) before anybody
starts working on it.
### ...but check for existing issues first!
Please take a moment to check that an issue doesn't already exist
documenting your bug report or improvement proposal. If it does, it
never hurts to add a quick "+1" or "I have this problem too". This will
help prioritize the most common problems and requests.
### Conventions
Fork the repo and make changes on your fork in a feature branch:
- If it's a bugfix branch, name it XXX-something where XXX is the number of the
issue
- If it's a feature branch, create an enhancement issue to announce your
intentions, and name it XXX-something where XXX is the number of the issue.
Submit unit tests for your changes. openHAB has a great test framework built in; use
it! Take a look at existing tests for inspiration. Run the full test suite on
your branch before submitting a pull request.
Update the documentation when creating or modifying features. Test
your documentation changes for clarity, concision, and correctness, as
well as a clean documentation build.
Write clean code. Universally formatted code promotes ease of writing, reading,
and maintenance.
Pull requests descriptions should be as clear as possible and include a
reference to all the issues that they address.
Pull requests must not contain commits from other users or branches.
Commit messages must start with a capitalized and short summary (max. 50
chars) written in the imperative, followed by an optional, more detailed
explanatory text which is separated from the summary by an empty line.
Code review comments may be added to your pull request. Discuss, then make the
suggested modifications and push additional commits to your feature branch. Be
sure to post a comment after pushing. The new commits will show up in the pull
request automatically, but the reviewers will not be notified unless you
comment.
Before the pull request is merged, make sure that you squash your commits into
logical units of work using `git rebase -i` and `git push -f`. After every
commit the test suite should be passing. Include documentation changes in the
same commit so that a revert would remove all traces of the feature or fix.
Commits that fix or close an issue should include a reference like `Closes #XXX`
or `Fixes #XXX`, which will automatically close the issue when merged.
Add your name to the AUTHORS file, but make sure the list is sorted and your
name and email address match your git configuration. The AUTHORS file is
regenerated occasionally from the git commit history, so a mismatch may result
in your changes being overwritten.
### Merge approval
openHAB maintainers use LGTM (Looks Good To Me) in comments on the code review
to indicate acceptance.
A change requires LGTMs from an absolute majority of the maintainers of each
component affected. For example, if a change affects `docs/` and `addons/`, it
needs an absolute majority from the maintainers of `docs/` AND, separately, an
absolute majority of the maintainers of `addons/`.
For more details see [MAINTAINERS.md](project-orga/MAINTAINERS.md)
### Sign your work
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right to
pass it on as an open-source patch. The rules are pretty simple: if you
can certify the below (from
[developercertificate.org](http://developercertificate.org/)):
```
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
then you just add a line to every git commit message:
Signed-off-by: Joe Smith <joe.smith@email.com> (github: github_handle)
using your real name (sorry, no pseudonyms or anonymous contributions.)
One way to automate this, is customise your get ``commit.template`` by adding
a ``prepare-commit-msg`` hook to your openHAB checkout:
```
curl -L -o .git/hooks/prepare-commit-msg https://raw.github.com/openhab/openhab2/master/contrib/prepare-commit-msg.hook && chmod +x .git/hooks/prepare-commit-msg
```
* Note: the above script expects to find your GitHub user name in ``git config --get github.user``
#### Small patch exception
There are several exceptions to the signing requirement. Currently these are:
* Your patch fixes spelling or grammar errors.
* Your patch is a single line change to documentation.
### How can I become a maintainer?
* Step 1: learn the component inside out
* Step 2: make yourself useful by contributing code, bugfixes, support etc.
* Step 3: volunteer on [the discussion group] (https://github.com/openhab/openhab2/issues?labels=question&page=1&state=open)
Don't forget: being a maintainer is a time investment. Make sure you will have time to make yourself available.
You don't have to be a maintainer to make a difference on the project!
## Community Guidelines
We want to keep the openHAB community awesome, growing and collaborative. We
need your help to keep it that way. To help with this we've come up with some
general guidelines for the community as a whole:
* Be nice: Be courteous, respectful and polite to fellow community members: no
regional, racial, gender, or other abuse will be tolerated. We like nice people
way better than mean ones!
* Encourage diversity and participation: Make everyone in our community
feel welcome, regardless of their background and the extent of their
contributions, and do everything possible to encourage participation in
our community.
* Keep it legal: Basically, don't get us in trouble. Share only content that
you own, do not share private or sensitive information, and don't break the
law.
* Stay on topic: Make sure that you are posting to the correct channel
and avoid off-topic discussions. Remember when you update an issue or
respond to an email you are potentially sending to a large number of
people. Please consider this before you update. Also remember that
nobody likes spam.
+203
View File
@@ -0,0 +1,203 @@
Eclipse Public License - v 1.0
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
1. DEFINITIONS
"Contribution" means:
a) in the case of the initial Contributor, the initial code and documentation
distributed under this Agreement, and
b) in the case of each subsequent Contributor:
i) changes to the Program, and
ii) additions to the Program;
where such changes and/or additions to the Program originate from and are
distributed by that particular Contributor. A Contribution 'originates'
from a Contributor if it was added to the Program by such Contributor
itself or anyone acting on such Contributor's behalf. Contributions do not
include additions to the Program which: (i) are separate modules of
software distributed in conjunction with the Program under their own
license agreement, and (ii) are not derivative works of the Program.
"Contributor" means any person or entity that distributes the Program.
"Licensed Patents" mean patent claims licensable by a Contributor which are
necessarily infringed by the use or sale of its Contribution alone or when
combined with the Program.
"Program" means the Contributions distributed in accordance with this
Agreement.
"Recipient" means anyone who receives the Program under this Agreement,
including all Contributors.
2. GRANT OF RIGHTS
a) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free copyright license to
reproduce, prepare derivative works of, publicly display, publicly
perform, distribute and sublicense the Contribution of such Contributor,
if any, and such derivative works, in source code and object code form.
b) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free patent license under
Licensed Patents to make, use, sell, offer to sell, import and otherwise
transfer the Contribution of such Contributor, if any, in source code and
object code form. This patent license shall apply to the combination of
the Contribution and the Program if, at the time the Contribution is
added by the Contributor, such addition of the Contribution causes such
combination to be covered by the Licensed Patents. The patent license
shall not apply to any other combinations which include the Contribution.
No hardware per se is licensed hereunder.
c) Recipient understands that although each Contributor grants the licenses
to its Contributions set forth herein, no assurances are provided by any
Contributor that the Program does not infringe the patent or other
intellectual property rights of any other entity. Each Contributor
disclaims any liability to Recipient for claims brought by any other
entity based on infringement of intellectual property rights or
otherwise. As a condition to exercising the rights and licenses granted
hereunder, each Recipient hereby assumes sole responsibility to secure
any other intellectual property rights needed, if any. For example, if a
third party patent license is required to allow Recipient to distribute
the Program, it is Recipient's responsibility to acquire that license
before distributing the Program.
d) Each Contributor represents that to its knowledge it has sufficient
copyright rights in its Contribution, if any, to grant the copyright
license set forth in this Agreement.
3. REQUIREMENTS
A Contributor may choose to distribute the Program in object code form under
its own license agreement, provided that:
a) it complies with the terms and conditions of this Agreement; and
b) its license agreement:
i) effectively disclaims on behalf of all Contributors all warranties
and conditions, express and implied, including warranties or
conditions of title and non-infringement, and implied warranties or
conditions of merchantability and fitness for a particular purpose;
ii) effectively excludes on behalf of all Contributors all liability for
damages, including direct, indirect, special, incidental and
consequential damages, such as lost profits;
iii) states that any provisions which differ from this Agreement are
offered by that Contributor alone and not by any other party; and
iv) states that source code for the Program is available from such
Contributor, and informs licensees how to obtain it in a reasonable
manner on or through a medium customarily used for software exchange.
When the Program is made available in source code form:
a) it must be made available under this Agreement; and
b) a copy of this Agreement must be included with each copy of the Program.
Contributors may not remove or alter any copyright notices contained
within the Program.
Each Contributor must identify itself as the originator of its Contribution,
if
any, in a manner that reasonably allows subsequent Recipients to identify the
originator of the Contribution.
4. COMMERCIAL DISTRIBUTION
Commercial distributors of software may accept certain responsibilities with
respect to end users, business partners and the like. While this license is
intended to facilitate the commercial use of the Program, the Contributor who
includes the Program in a commercial product offering should do so in a manner
which does not create potential liability for other Contributors. Therefore,
if a Contributor includes the Program in a commercial product offering, such
Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
every other Contributor ("Indemnified Contributor") against any losses,
damages and costs (collectively "Losses") arising from claims, lawsuits and
other legal actions brought by a third party against the Indemnified
Contributor to the extent caused by the acts or omissions of such Commercial
Contributor in connection with its distribution of the Program in a commercial
product offering. The obligations in this section do not apply to any claims
or Losses relating to any actual or alleged intellectual property
infringement. In order to qualify, an Indemnified Contributor must:
a) promptly notify the Commercial Contributor in writing of such claim, and
b) allow the Commercial Contributor to control, and cooperate with the
Commercial Contributor in, the defense and any related settlement
negotiations. The Indemnified Contributor may participate in any such claim at
its own expense.
For example, a Contributor might include the Program in a commercial product
offering, Product X. That Contributor is then a Commercial Contributor. If
that Commercial Contributor then makes performance claims, or offers
warranties related to Product X, those performance claims and warranties are
such Commercial Contributor's responsibility alone. Under this section, the
Commercial Contributor would have to defend claims against the other
Contributors related to those performance claims and warranties, and if a
court requires any other Contributor to pay any damages as a result, the
Commercial Contributor must pay those damages.
5. NO WARRANTY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
Recipient is solely responsible for determining the appropriateness of using
and distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement , including but not limited to the
risks and costs of program errors, compliance with applicable laws, damage to
or loss of data, programs or equipment, and unavailability or interruption of
operations.
6. DISCLAIMER OF LIABILITY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGES.
7. GENERAL
If any provision of this Agreement is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of the
remainder of the terms of this Agreement, and without further action by the
parties hereto, such provision shall be reformed to the minimum extent
necessary to make such provision valid and enforceable.
If Recipient institutes patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Program itself
(excluding combinations of the Program with other software or hardware)
infringes such Recipient's patent(s), then such Recipient's rights granted
under Section 2(b) shall terminate as of the date such litigation is filed.
All Recipient's rights under this Agreement shall terminate if it fails to
comply with any of the material terms or conditions of this Agreement and does
not cure such failure in a reasonable period of time after becoming aware of
such noncompliance. If all Recipient's rights under this Agreement terminate,
Recipient agrees to cease use and distribution of the Program as soon as
reasonably practicable. However, Recipient's obligations under this Agreement
and any licenses granted by Recipient relating to the Program shall continue
and survive.
Everyone is permitted to copy and distribute copies of this Agreement, but in
order to avoid inconsistency the Agreement is copyrighted and may only be
modified in the following manner. The Agreement Steward reserves the right to
publish new versions (including revisions) of this Agreement from time to
time. No one other than the Agreement Steward has the right to modify this
Agreement. The Eclipse Foundation is the initial Agreement Steward. The
Eclipse Foundation may assign the responsibility to serve as the Agreement
Steward to a suitable separate entity. Each new version of the Agreement will
be given a distinguishing version number. The Program (including
Contributions) may always be distributed subject to the version of the
Agreement under which it was received. In addition, after a new version of the
Agreement is published, Contributor may elect to distribute the Program
(including its Contributions) under the new version. Except as expressly
stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
licenses to the intellectual property of any Contributor under this Agreement,
whether expressly, by implication, estoppel or otherwise. All rights in the
Program not expressly granted under this Agreement are reserved.
This Agreement is governed by the laws of the State of New York and the
intellectual property laws of the United States of America. No party to this
Agreement will bring a legal action under this Agreement more than one year
after the cause of action arose. Each party waives its rights to a jury trial in
any resulting litigation.
+2
View File
@@ -0,0 +1,2 @@
This project contains some core bundles of the openHAB 2 runtime.
They are picked up by the openHAB distribution build.
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="src" path="src/test/groovy"/>
<classpathentry exported="true" kind="con" path="GROOVY_SUPPORT"/>
<classpathentry exported="true" kind="con" path="GROOVY_DSL_SUPPORT"/>
<classpathentry kind="output" path="target/test-classes"/>
</classpath>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.compat1x.test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
@@ -0,0 +1,4 @@
eclipse.preferences.version=1
pluginProject.equinox=false
pluginProject.extensions=false
resolve.requirebundle=false
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: openHAB 1.x Compatibility Layer Tests
Bundle-SymbolicName: org.openhab.core.compat1x.test
Bundle-Version: 2.0.0.qualifier
Bundle-Vendor: openHAB.org
Fragment-Host: org.openhab.core.compat1x
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: groovy.lang,
org.codehaus.groovy.reflection,
org.codehaus.groovy.runtime,
org.codehaus.groovy.runtime.callsite,
org.codehaus.groovy.runtime.typehandling,
org.eclipse.smarthome.core.events,
org.eclipse.smarthome.test,
org.hamcrest;core=split,
org.junit
@@ -0,0 +1,5 @@
source.. = src/test/java/,\
src/test/groovy/
output.. = target/test-classes/
bin.includes = META-INF/,\
.
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.bundles</groupId>
<artifactId>pom</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.compat1x.test</artifactId>
<name>openHAB Core 1.x Compatibility Layer Tests</name>
<packaging>eclipse-test-plugin</packaging>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
<dependencies>
<dependency>
<type>eclipse-plugin</type>
<artifactId>org.eclipse.equinox.ds</artifactId>
<version>0.0.0</version>
</dependency>
</dependencies>
<bundleStartLevel>
<bundle>
<id>org.eclipse.equinox.ds</id>
<level>1</level>
<autoStart>true</autoStart>
</bundle>
</bundleStartLevel>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,78 @@
/**
* Copyright (c) 2014-2015 openHAB UG (haftungsbeschraenkt) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events
import static org.hamcrest.CoreMatchers.*
import static org.junit.Assert.*
import static org.junit.matchers.JUnitMatchers.*
import org.eclipse.smarthome.core.events.Event
import org.eclipse.smarthome.core.events.EventFilter
import org.eclipse.smarthome.core.items.ItemProvider;
import org.eclipse.smarthome.core.library.items.StringItem
import org.eclipse.smarthome.test.OSGiTest
import org.junit.Before
import org.junit.Test
import org.openhab.core.library.types.StringType
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* Tests for {@link EventDelegate}.
*
* @author Kai Kreuzer - Initial version
* @since 2.0
*/
class EventDelegateTest extends OSGiTest {
def state
EventPublisher publisher
org.eclipse.smarthome.core.events.EventSubscriber eventSubscriber = new org.eclipse.smarthome.core.events.EventSubscriber() {
@Override
public void receive(Event event) {
state = newState
}
Set getSubscribedEventTypes() {};
EventFilter getEventFilter() { return null };
}
@Before
void setUp() {
registerService([
getAll: {
[
new StringItem("Test")
]
},
addProviderChangeListener: {},
removeProviderChangeListener: {},
allItemsChanged: {}] as ItemProvider)
registerService(eventSubscriber, org.osgi.service.event.EventHandler.class.name, ["event.topics":"smarthome/*"] as Hashtable)
publisher = getService(org.openhab.core.events.EventPublisher, EventPublisherDelegate)
assertThat publisher, is(notNullValue())
}
@Test
void testMapUnDefType() {
publisher.postUpdate("Test", new StringType("ABC"))
waitFor ( { state != null }, 2000)
assertEquals "ABC", state.toString()
publisher.postUpdate("Test", UnDefType.NULL)
waitFor ( { state != null }, 2000)
assertEquals org.eclipse.smarthome.core.types.UnDefType.NULL, state
publisher.postUpdate("Test", UnDefType.UNDEF)
waitFor ( { state != null }, 2000)
assertEquals org.eclipse.smarthome.core.types.UnDefType.UNDEF, state
}
}
@@ -0,0 +1,98 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.compat1x.internal;
import static org.junit.Assert.*;
import org.eclipse.smarthome.core.items.GroupItem;
import org.eclipse.smarthome.core.library.items.ColorItem;
import org.eclipse.smarthome.core.library.items.ContactItem;
import org.eclipse.smarthome.core.library.items.DateTimeItem;
import org.eclipse.smarthome.core.library.items.DimmerItem;
import org.eclipse.smarthome.core.library.items.NumberItem;
import org.eclipse.smarthome.core.library.items.RollershutterItem;
import org.eclipse.smarthome.core.library.items.StringItem;
import org.eclipse.smarthome.core.library.items.SwitchItem;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.types.UnDefType;
import org.junit.Test;
import org.openhab.core.items.Item;
public class ItemMapperTest {
@Test
public void testESH2OHItemMapping() {
Item item = null;
item = ItemMapper.mapToOpenHABItem(new StringItem("test1"));
assertEquals(org.openhab.core.library.items.StringItem.class, item.getClass());
assertEquals("test1", item.getName());
item = ItemMapper.mapToOpenHABItem(new NumberItem("test2"));
assertEquals(org.openhab.core.library.items.NumberItem.class, item.getClass());
assertEquals("test2", item.getName());
item = ItemMapper.mapToOpenHABItem(new DimmerItem("test3"));
assertEquals(org.openhab.core.library.items.DimmerItem.class, item.getClass());
assertEquals("test3", item.getName());
item = ItemMapper.mapToOpenHABItem(new RollershutterItem("test4"));
assertEquals(org.openhab.core.library.items.RollershutterItem.class, item.getClass());
assertEquals("test4", item.getName());
item = ItemMapper.mapToOpenHABItem(new ColorItem("test5"));
assertEquals(org.openhab.core.library.items.ColorItem.class, item.getClass());
assertEquals("test5", item.getName());
item = ItemMapper.mapToOpenHABItem(new ContactItem("test6"));
assertEquals(org.openhab.core.library.items.ContactItem.class, item.getClass());
assertEquals("test6", item.getName());
item = ItemMapper.mapToOpenHABItem(new DateTimeItem("test7"));
assertEquals(org.openhab.core.library.items.DateTimeItem.class, item.getClass());
assertEquals("test7", item.getName());
item = ItemMapper.mapToOpenHABItem(new SwitchItem("test8"));
assertEquals(org.openhab.core.library.items.SwitchItem.class, item.getClass());
assertEquals("test8", item.getName());
}
@Test
public void testGroupItemMapping() {
org.openhab.core.items.GroupItem group = (org.openhab.core.items.GroupItem) ItemMapper.mapToOpenHABItem(new GroupItem("group1"));
assertEquals("group1", group.getName());
assertNull(group.getBaseItem());
group = (org.openhab.core.items.GroupItem) ItemMapper.mapToOpenHABItem(new GroupItem("group2", new NumberItem("baseItem")));
assertEquals("group2", group.getName());
assertEquals(org.openhab.core.library.items.NumberItem.class, group.getBaseItem().getClass());
GroupItem eshGroup = new GroupItem("group3");
for(int i = 1; i <= 10; i++) {
eshGroup.addMember(new StringItem(Integer.toString(i)));
}
group = (org.openhab.core.items.GroupItem) ItemMapper.mapToOpenHABItem(eshGroup);
assertEquals("group3", group.getName());
assertEquals(10, group.getMembers().size());
assertEquals(org.openhab.core.library.items.StringItem.class, group.getMembers().iterator().next().getClass());
}
@Test
public void testItemStateMapping() {
StringItem item = new StringItem("test");
item.setState(UnDefType.NULL);
assertEquals(org.openhab.core.types.UnDefType.NULL, ItemMapper.mapToOpenHABItem(item).getState());
item.setState(UnDefType.UNDEF);
assertEquals(org.openhab.core.types.UnDefType.UNDEF, ItemMapper.mapToOpenHABItem(item).getState());
item.setState(new StringType("ABC"));
assertEquals(new org.openhab.core.library.types.StringType("ABC"), ItemMapper.mapToOpenHABItem(item).getState());
}
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="lib" path="lib/jl1.0.1.jar"/>
<classpathentry exported="true" kind="lib" path="lib/jackson-core-asl-1.9.2.jar"/>
<classpathentry exported="true" kind="lib" path="lib/jackson-mapper-asl-1.9.2.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.core.compat1x</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
@@ -0,0 +1,4 @@
eclipse.preferences.version=1
pluginProject.equinox=false
pluginProject.extensions=false
resolve.requirebundle=false
@@ -0,0 +1,104 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: openHAB 1.x Compatibility Layer
Bundle-SymbolicName: org.openhab.core.compat1x
Bundle-Version: 2.0.0.qualifier
Bundle-Activator: org.openhab.core.compat1x.internal.CompatibilityActivator
Bundle-Vendor: openHAB.org
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: com.google.common.base,
javax.servlet,
javax.servlet.http,
javax.sound.sampled,
org.apache.commons.collections,
org.apache.commons.exec,
org.apache.commons.httpclient,
org.apache.commons.httpclient.auth,
org.apache.commons.httpclient.methods,
org.apache.commons.httpclient.params,
org.apache.commons.io,
org.apache.commons.lang,
org.apache.commons.net.util,
org.eclipse.emf.common.util,
org.eclipse.emf.ecore,
org.eclipse.emf.ecore.resource,
org.eclipse.smarthome.core.autoupdate,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.events,
org.eclipse.smarthome.core.items,
org.eclipse.smarthome.core.items.events,
org.eclipse.smarthome.core.library.items,
org.eclipse.smarthome.core.library.types,
org.eclipse.smarthome.core.persistence,
org.eclipse.smarthome.core.transform,
org.eclipse.smarthome.core.types,
org.eclipse.smarthome.io.multimedia.tts,
org.eclipse.smarthome.model.item,
org.eclipse.smarthome.model.persistence,
org.eclipse.smarthome.model.script.engine,
org.eclipse.smarthome.model.script.engine.action,
org.eclipse.smarthome.model.sitemap,
org.eclipse.smarthome.ui.chart,
org.eclipse.smarthome.ui.items,
org.openhab.io.multimedia.actions,
org.openhab.library.tel.types,
org.osgi.framework,
org.osgi.service.cm,
org.osgi.service.event,
org.osgi.service.http,
org.osgi.util.tracker,
org.slf4j
Export-Package: org.codehaus.jackson,
org.codehaus.jackson.annotate,
org.codehaus.jackson.format,
org.codehaus.jackson.impl,
org.codehaus.jackson.io,
org.codehaus.jackson.map,
org.codehaus.jackson.map.annotate,
org.codehaus.jackson.map.deser,
org.codehaus.jackson.map.deser.impl,
org.codehaus.jackson.map.deser.std,
org.codehaus.jackson.map.exc,
org.codehaus.jackson.map.ext,
org.codehaus.jackson.map.introspect,
org.codehaus.jackson.map.jsontype,
org.codehaus.jackson.map.jsontype.impl,
org.codehaus.jackson.map.module,
org.codehaus.jackson.map.ser,
org.codehaus.jackson.map.ser.impl,
org.codehaus.jackson.map.ser.std,
org.codehaus.jackson.map.type,
org.codehaus.jackson.map.util,
org.codehaus.jackson.node,
org.codehaus.jackson.schema,
org.codehaus.jackson.sym,
org.codehaus.jackson.type,
org.codehaus.jackson.util,
org.openhab.core.autoupdate,
org.openhab.core.binding,
org.openhab.core.events;uses:="org.openhab.core.items,org.osgi.service.event,org.openhab.core.types",
org.openhab.core.items;uses:="org.openhab.core.types,org.openhab.core.events",
org.openhab.core.library.items,
org.openhab.core.library.types,
org.openhab.core.persistence,
org.openhab.core.scriptengine.action,
org.openhab.core.service,
org.openhab.core.transform,
org.openhab.core.transform.actions,
org.openhab.core.types,
org.openhab.io.console,
org.openhab.io.multimedia.actions,
org.openhab.io.multimedia.tts,
org.openhab.io.net.actions,
org.openhab.io.net.exec,
org.openhab.io.net.http,
org.openhab.library.tel.items,
org.openhab.library.tel.types,
org.openhab.model.item.binding,
org.openhab.ui.chart,
org.openhab.ui.items
Bundle-ClassPath: lib/jl1.0.1.jar,
.,
lib/jackson-core-asl-1.9.2.jar,
lib/jackson-mapper-asl-1.9.2.jar
Service-Component: OSGI-INF/*.xml
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="org.openhab.core.compat1x.actionservicefactory">
<implementation class="org.openhab.core.scriptengine.action.internal.ActionServiceFactory"/>
<reference bind="addActionService" cardinality="0..n" interface="org.openhab.core.scriptengine.action.ActionService" name="ActionService" policy="dynamic" unbind="removeActionService"/>
</scr:component>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.openhab.action.audio">
<implementation class="org.openhab.io.multimedia.actions.AudioActionService"/>
<service>
<provide interface="org.openhab.core.scriptengine.action.ActionService"/>
</service>
</scr:component>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.openhab.core.compat1x.autoupdateproviderdelegate">
<implementation class="org.openhab.core.autoupdate.internal.AutoUpdateProviderDelegate"/>
<reference bind="addAutoUpdateBindingProvider" cardinality="0..n" interface="org.openhab.core.autoupdate.AutoUpdateBindingProvider" name="AutoUpdateBindingProvider" policy="dynamic" unbind="removeAutoUpdateBindingProvider"/>
<service>
<provide interface="org.eclipse.smarthome.core.autoupdate.AutoUpdateBindingConfigProvider"/>
</service>
</scr:component>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.openhab.core.compat1x.bindingconfigreaderfactory">
<implementation class="org.openhab.core.binding.internal.BindingConfigReaderFactory"/>
<reference bind="addBindingConfigReader" cardinality="0..n" interface="org.openhab.model.item.binding.BindingConfigReader" name="BindingConfigReader" policy="dynamic" unbind="removeBindingConfigReader"/>
</scr:component>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="org.openhab.core.compat1x.chartproviderfactory" immediate="true" >
<implementation class="org.openhab.ui.chart.internal.ChartProviderFactory"/>
<reference bind="addChartProvider" cardinality="0..n" interface="org.openhab.ui.chart.ChartProvider" name="ChartProvider" policy="dynamic" unbind="removeChartProvider"/>
</scr:component>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.openhab.core.compat1x.eventbridge">
<implementation class="org.openhab.core.events.internal.EventBridge"/>
<service>
<provide interface="org.osgi.service.event.EventHandler"/>
<provide interface="org.eclipse.smarthome.core.events.EventSubscriber"/>
</service>
<reference bind="setEventAdmin" cardinality="1..1" interface="org.osgi.service.event.EventAdmin" name="EventAdmin" policy="dynamic" unbind="unsetEventAdmin"/>
<property name="event.topics" type="String" value="smarthome/*"/>
<reference bind="setEventPublisher" cardinality="1..1" interface="org.eclipse.smarthome.core.events.EventPublisher" name="EventPublisher" policy="static" unbind="unsetEventPublisher"/>
</scr:component>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.openhab.core.compat1x.eventpublisherdelegate">
<implementation class="org.openhab.core.events.EventPublisherDelegate"/>
<service>
<provide interface="org.openhab.core.events.EventPublisher"/>
</service>
<reference bind="setEventPublisher" cardinality="1..1" interface="org.eclipse.smarthome.core.events.EventPublisher" name="EventPublisher" policy="dynamic" unbind="unsetEventPublisher"/>
</scr:component>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.openhab.library.tel">
<implementation class="org.openhab.library.tel.internal.TelItemFactory"/>
<service>
<provide interface="org.eclipse.smarthome.core.items.ItemFactory"/>
</service>
</scr:component>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.openhab.core.compat1x.itemuiregistry">
<implementation class="org.openhab.core.items.internal.ItemUIRegistryDelegate"/>
<service>
<provide interface="org.openhab.core.items.ItemRegistry"/>
<provide interface="org.openhab.ui.items.ItemUIRegistry"/>
</service>
<reference bind="setItemUIRegistry" cardinality="1..1" interface="org.eclipse.smarthome.ui.items.ItemUIRegistry" name="ItemUIRegistry" policy="static" unbind="unsetItemUIRegistry"/>
</scr:component>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="org.openhab.core.compat1x.persistenceservicefactory">
<implementation class="org.openhab.core.persistence.internal.PersistenceServiceFactory"/>
<reference bind="addPersistenceService" cardinality="0..n" interface="org.openhab.core.persistence.PersistenceService" name="PersistenceService" policy="dynamic" unbind="removePersistenceService"/>
</scr:component>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015-2015 Kai Kreuzer and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="org.openhab.core.compat1x.ttsservicefactory">
<implementation class="org.openhab.io.multimedia.tts.internal.TTSServiceFactory"/>
<reference bind="addTTSService" cardinality="0..n" interface="org.openhab.io.multimedia.tts.TTSService" name="TTSService" policy="dynamic" unbind="removeTTSService"/>
</scr:component>
@@ -0,0 +1,16 @@
output.. = target/classes/
bin.includes = META-INF/,\
.,\
lib/,\
OSGI-INF/,\
OSGI-INF/autoupdateproviderdelegate.xml,\
OSGI-INF/eventbridge.xml,\
OSGI-INF/eventpublisherdelegate.xml,\
OSGI-INF/bindingconfigreaderfactory.xml,\
OSGI-INF/actionservicefactory.xml,\
OSGI-INF/itemuiregistry.xml,\
OSGI-INF/chartproviderfactory.xml,\
OSGI-INF/ttsservicefactory.xml,\
lib/jackson-core-asl-1.9.2.jar,\
lib/jackson-mapper-asl-1.9.2.jar
source.. = src/main/java/
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.bundles</groupId>
<artifactId>pom</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.compat1x</artifactId>
<name>openHAB Core 1.x Compatibility Layer</name>
<packaging>eclipse-plugin</packaging>
</project>
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.autoupdate;
import org.openhab.core.binding.BindingProvider;
/**
* This interface is implemented by classes that can provide configuration
* information of the AutoUpdate feature.
*
* Implementing classes should register themselves as a service in order to be
* taken into account.
*
* @author Thomas.Eichstaedt-Engelen
* @since 0.9.1
*/
public interface AutoUpdateBindingProvider extends BindingProvider {
/**
* Indicates whether an Item with the given <code>itemName</code> is
* configured to automatically update it's State after receiving a Command
* or not.
*
* @param itemName the name of the Item for which to find the configuration
* @return <code>false</code> to disable the automatic update,
* <code>true</code> to enable the automatic update and <code>null</code>
* if there is no configuration for this item.
*/
Boolean autoUpdate(String itemName);
}
@@ -0,0 +1,45 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.autoupdate.internal;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.smarthome.core.autoupdate.AutoUpdateBindingConfigProvider;
/**
* This class serves as a mapping from the "old" org.openhab namespace to the new org.eclipse.smarthome
* namespace for the auto update provider. It gathers all services that implement the old interface
* and makes them available as single provider of the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class AutoUpdateProviderDelegate implements AutoUpdateBindingConfigProvider {
private Set<org.openhab.core.autoupdate.AutoUpdateBindingProvider> providers = new CopyOnWriteArraySet<>();
public void addAutoUpdateBindingProvider(org.openhab.core.autoupdate.AutoUpdateBindingProvider provider) {
providers.add(provider);
}
public void removeAutoUpdateBindingProvider(org.openhab.core.autoupdate.AutoUpdateBindingProvider provider) {
providers.remove(provider);
}
@Override
public Boolean autoUpdate(String itemName) {
for(org.openhab.core.autoupdate.AutoUpdateBindingProvider provider : providers) {
Boolean autoUpdate = provider.autoUpdate(itemName);
if(autoUpdate!=null) {
return autoUpdate;
}
}
return null;
}
}
@@ -0,0 +1,172 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding;
import org.openhab.core.service.AbstractActiveService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base class for active bindings which polls something and sends events frequently.
*
* @author Thomas.Eichstaedt-Engelen
* @author Kai Kreuzer
*
* @since 0.6.0
*/
public abstract class AbstractActiveBinding<P extends BindingProvider> extends AbstractBinding<P> {
private static final Logger logger = LoggerFactory.getLogger(AbstractActiveBinding.class);
/** embedded active service to allow the binding to have some code executed in a given interval. */
protected AbstractActiveService activeService = new BindingActiveService();
/**
* Adds <code>provider</code> to the list of {@link BindingProvider}s and
* adds <code>this</code> as {@link BindingConfigChangeListener}. If
* <code>provider</code> contains any binding an the refresh-Thread is
* stopped it will be started.
*
* @param provider the new {@link BindingProvider} to add
*/
@Override
public void addBindingProvider(BindingProvider provider) {
super.addBindingProvider(provider);
activeService.activate();
}
/**
* Removes <code>provider</code> from the list of providers. If there is no
* provider left the refresh thread is getting interrupted.
*
* @param provider the {@link BindingProvider} to remove
*/
@Override
public void removeBindingProvider(BindingProvider provider) {
super.removeBindingProvider(provider);
// if there are no binding providers there is no need to run this
// refresh thread any longer ...
if (this.providers.size() == 0) {
activeService.deactivate();
}
}
/**
* {@inheritDoc}
*/
@Override
public void bindingChanged(BindingProvider provider, String itemName) {
super.bindingChanged(provider, itemName);
if (bindingsExist()) {
activeService.activate();
} else {
activeService.deactivate();
}
}
/**
* {@inheritDoc}
*/
@Override
public void allBindingsChanged(BindingProvider provider) {
super.allBindingsChanged(provider);
if (bindingsExist()) {
activeService.activate();
} else {
activeService.deactivate();
}
}
/**
* Used to define whether this binding is fully configured so that it can be
* activated and used.
* Note that the implementation will automatically start the active service if
* <code>true</code> is passed as a parameter and there are binding providers available.
*
* @param properlyConfigured
*/
protected void setProperlyConfigured(boolean properlyConfigured) {
if (providers.size() > 0) {
activeService.setProperlyConfigured(properlyConfigured);
}
}
/**
* @return <code>true</code> if this binding is configured properly which means
* that all necessary data is available
*/
protected boolean isProperlyConfigured() {
return activeService.isProperlyConfigured();
}
/**
* The working method which is called by the refresh thread frequently.
* Developers should put their binding code here.
*/
protected abstract void execute();
/**
* Returns the refresh interval to be used by the RefreshThread between to
* calls of the execute method.
*
* @return the refresh interval
*/
protected abstract long getRefreshInterval();
/**
* Returns the name of the Refresh thread.
*
* @return the name of the refresh thread.
*/
protected abstract String getName();
/** private inner class, which delegates method calls to the outer binding instance */
private class BindingActiveService extends AbstractActiveService {
/**
* {@inheritDoc}
*/
@Override
protected void start() {
super.start();
}
/**
* @{inheritDoc}
*/
@Override
public void interrupt() {
if (!bindingsExist()) {
super.interrupt();
} else {
logger.trace("{} won't be interrupted because bindings exist.", getName());
}
}
@Override
protected void execute() {
AbstractActiveBinding.this.execute();
}
@Override
protected long getRefreshInterval() {
return AbstractActiveBinding.this.getRefreshInterval();
}
@Override
protected String getName() {
return AbstractActiveBinding.this.getName();
}
}
}
@@ -0,0 +1,163 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArraySet;
import org.openhab.core.events.AbstractEventSubscriber;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* Base class for bindings which send events.
*
* @author Thomas.Eichstaedt-Engelen
* @author Kai Kreuzer
* @since 1.0.0
*/
public abstract class AbstractBinding<P extends BindingProvider> extends AbstractEventSubscriber
implements BindingChangeListener {
/** to keep track of all binding providers */
protected Collection<P> providers = new CopyOnWriteArraySet<P>();
protected EventPublisher eventPublisher = null;
public void setEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void unsetEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = null;
}
public void activate() {
};
public void deactivate() {
};
/**
* Adds <code>provider</code> to the list of {@link BindingProvider}s and
* adds <code>this</code> as {@link BindingConfigChangeListener}. If
* <code>provider</code> contains any binding an the refresh-Thread is
* stopped it will be started.
*
* @param provider the new {@link BindingProvider} to add
*/
@SuppressWarnings("unchecked")
public void addBindingProvider(BindingProvider provider) {
this.providers.add((P) provider);
provider.addBindingChangeListener(this);
allBindingsChanged(provider);
}
/**
* Removes <code>provider</code> from the list of providers. If there is no
* provider left the refresh thread is getting interrupted.
*
* @param provider the {@link BindingProvider} to remove
*/
public void removeBindingProvider(BindingProvider provider) {
this.providers.remove(provider);
provider.removeBindingChangeListener(this);
}
/**
* @return <code>true</code> if any of the {@link BindingProvider}s provides
* a binding
*/
protected boolean bindingsExist() {
for (BindingProvider provider : providers) {
if (provider.providesBinding()) {
return true;
}
}
return false;
}
/**
* @{inheritDoc}
*/
@Override
public void receiveCommand(String itemName, Command command) {
// does any provider contain a binding config?
if (!providesBindingFor(itemName)) {
return;
}
internalReceiveCommand(itemName, command);
}
/**
* Is called by <code>receiveCommand()</code> only if one of the
* {@link BindingProvider}s provide a binding for <code>itemName</code>.
*
* @param itemName the item on which <code>command</code> will be executed
* @param command the {@link Command} to be executed on <code>itemName</code>
*/
protected void internalReceiveCommand(String itemName, Command command) {
};
/**
* @{inheritDoc}
*/
@Override
public void receiveUpdate(String itemName, State newState) {
// does any provider contain a binding config?
if (!providesBindingFor(itemName)) {
return;
}
internalReceiveUpdate(itemName, newState);
}
/**
* Is called by <code>receiveUpdate()</code> only if one of the
* {@link BindingProvider}s provide a binding for <code>itemName</code>.
*
* @param itemName the item on which <code>command</code> will be executed
* @param newState the {@link State} to be update
*/
protected void internalReceiveUpdate(String itemName, State newState) {
};
/**
* checks if any of the bindingProviders contains an adequate mapping
*
* @param itemName the itemName to check
* @return <code>true</code> if any of the bindingProviders contains an
* adequate mapping for <code>itemName</code> and <code>false</code>
* otherwise
*/
protected boolean providesBindingFor(String itemName) {
for (P provider : providers) {
if (provider.providesBindingFor(itemName)) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void allBindingsChanged(BindingProvider provider) {
}
/**
* {@inheritDoc}
*/
@Override
public void bindingChanged(BindingProvider provider, String itemName) {
}
}
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding;
/**
* This interface must be implemented by classes which want to be notified by a
* {@link BindingProvider} about changes in the binding configuration.
*
* @author Kai Kreuzer
* @since 0.3.0
*/
public interface BindingChangeListener {
/**
* Called, if a single binding has changed. The given item could have been
* added or removed.
*
* @param provider the binding provider where the binding has changed
* @param itemName the item name for which the binding has changed
*/
public void bindingChanged(BindingProvider provider, String itemName);
/**
* Called, if all bindings (might) have changed.
*
* @param provider the binding provider whose bindings have changed
*/
public void allBindingsChanged(BindingProvider provider);
}
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding;
/**
* This is a simple marker interface to define data structures that are
* used as binding configurations.
*
* @author Kai Kreuzer
* @since 0.6.0
*
*/
public interface BindingConfig {
}
@@ -0,0 +1,62 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding;
import java.util.Collection;
/**
* @author Thomas.Eichstaedt-Engelen
* @author Kai Kreuzer
* @since 0.6.0
*/
public interface BindingProvider {
/**
* Adds a binding change listener, which gets notified whenever there
* are changes in the binding configuration
*
* @param listener the binding change listener to add
*/
public void addBindingChangeListener(BindingChangeListener listener);
/**
* Removes a binding change listener again.
* Does nothing, if this listener has not been added before.
*
* @param listener the binding listener to remove
*/
public void removeBindingChangeListener(BindingChangeListener listener);
/**
* Indicates whether this binding provider contains a binding for the given
* <code>itemName</code>
*
* @param itemName the itemName to check
*
* @return <code>true</code> if this provider contains an adequate mapping
* for <code>itemName</code> and <code>false</code> otherwise.
*/
boolean providesBindingFor(String itemName);
/**
* Indicates whether this binding provider contains any binding
*
* @return <code>true</code> if this provider contains any binding
* configuration and <code>false</code> otherwise
*/
boolean providesBinding();
/**
* Returns all items which are mapped to this binding
* @return items which are mapped to this binding
*/
Collection<String> getItemNames();
}
@@ -0,0 +1,87 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding.internal;
import org.eclipse.smarthome.model.item.BindingConfigParseException;
import org.eclipse.smarthome.model.item.BindingConfigReader;
/**
* This class serves as a mapping from the "old" org.openhab namespace to the new org.eclipse.smarthome
* namespace for the binding config readers. It wraps an instance with the old interface
* into a class with the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class BindingConfigReaderDelegate implements BindingConfigReader {
private org.openhab.model.item.binding.BindingConfigReader reader;
public BindingConfigReaderDelegate(
org.openhab.model.item.binding.BindingConfigReader reader) {
this.reader = reader;
}
@Override
public String getBindingType() {
return reader.getBindingType();
}
@Override
public void validateItemType(String itemType, String bindingConfig)
throws BindingConfigParseException {
try {
reader.validateItemType(getOpenHABItem(itemType), bindingConfig);
} catch (org.openhab.model.item.binding.BindingConfigParseException e) {
throw new BindingConfigParseException(e.getMessage());
}
}
@Override
public void processBindingConfiguration(String context, String itemType, String itemName,
String bindingConfig) throws BindingConfigParseException {
try {
reader.processBindingConfiguration(context, getOpenHABItem(itemType, itemName), bindingConfig);
} catch (org.openhab.model.item.binding.BindingConfigParseException e) {
throw new BindingConfigParseException(e.getMessage());
}
}
private org.openhab.core.items.Item getOpenHABItem(String itemType) throws BindingConfigParseException {
return getOpenHABItem(itemType, "itemName");
}
private org.openhab.core.items.Item getOpenHABItem(String itemType,
String itemName) throws BindingConfigParseException {
switch(itemType) {
case "Switch" : return new org.openhab.core.library.items.SwitchItem(itemName);
case "Dimmer" : return new org.openhab.core.library.items.DimmerItem(itemName);
case "Color" : return new org.openhab.core.library.items.ColorItem(itemName);
case "String" : return new org.openhab.core.library.items.StringItem(itemName);
case "Number" : return new org.openhab.core.library.items.NumberItem(itemName);
case "Contact" : return new org.openhab.core.library.items.ContactItem(itemName);
case "Rollershutter" : return new org.openhab.core.library.items.RollershutterItem(itemName);
case "DateTime" : return new org.openhab.core.library.items.DateTimeItem(itemName);
case "Call" : return new org.openhab.library.tel.items.CallItem(itemName);
}
throw new BindingConfigParseException("cannot process unknown item type " + itemType);
}
@Override
public void startConfigurationUpdate(String context) {
reader.removeConfigurations(context);
}
@Override
public void stopConfigurationUpdate(String context) {
}
}
@@ -0,0 +1,82 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.binding.internal;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import org.openhab.model.item.binding.BindingConfigReader;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
/**
* This class listens for services that implement the old binding config reader interface and registers
* an according service for each under the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class BindingConfigReaderFactory {
private Map<String, ServiceRegistration<org.eclipse.smarthome.model.item.BindingConfigReader>> delegates = new HashMap<>();
private BundleContext context;
private Set<BindingConfigReader> readers = new HashSet<>();
public void activate(BundleContext context) {
this.context = context;
for(BindingConfigReader reader : readers) {
registerDelegateService(reader);
}
}
public void deactivate() {
for(ServiceRegistration<org.eclipse.smarthome.model.item.BindingConfigReader> serviceReg : delegates.values()) {
serviceReg.unregister();
}
delegates.clear();
this.context = null;
}
public void addBindingConfigReader(BindingConfigReader reader) {
if(context!=null) {
registerDelegateService(reader);
} else {
readers.add(reader);
}
}
public void removeBindingConfigReader(BindingConfigReader reader) {
if(context!=null) {
unregisterDelegateService(reader);
}
}
private void registerDelegateService(BindingConfigReader reader) {
if(!delegates.containsKey(reader.getBindingType())) {
BindingConfigReaderDelegate service = new BindingConfigReaderDelegate(reader);
Dictionary<String, Object> props = new Hashtable<String, Object>();
ServiceRegistration<org.eclipse.smarthome.model.item.BindingConfigReader> serviceReg =
context.registerService(org.eclipse.smarthome.model.item.BindingConfigReader.class, service, props);
delegates.put(reader.getBindingType(), serviceReg);
}
}
private void unregisterDelegateService(BindingConfigReader reader) {
if(delegates.containsKey(reader.getBindingType())) {
ServiceRegistration<org.eclipse.smarthome.model.item.BindingConfigReader> serviceReg =
delegates.get(reader.getBindingType());
delegates.remove(reader.getBindingType());
serviceReg.unregister();
}
}
}
@@ -0,0 +1,65 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.compat1x.internal;
import org.eclipse.smarthome.model.script.engine.ScriptEngine;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.items.ItemRegistry;
import org.openhab.io.multimedia.actions.Audio;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
public class CompatibilityActivator implements BundleActivator {
private static BundleContext context;
public static ServiceTracker<ItemRegistry, ItemRegistry> itemRegistryTracker;
public static ServiceTracker<EventPublisher, EventPublisher> eventPublisherTracker;
public static ServiceTracker<ScriptEngine, ScriptEngine> scriptEngineTracker;
static public BundleContext getContext() {
return context;
}
/*
* (non-Javadoc)
*
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
@Override
public void start(BundleContext bundleContext) throws Exception {
CompatibilityActivator.context = bundleContext;
itemRegistryTracker = new ServiceTracker<ItemRegistry, ItemRegistry>(bundleContext, ItemRegistry.class, null);
itemRegistryTracker.open();
eventPublisherTracker = new ServiceTracker<EventPublisher, EventPublisher>(bundleContext, EventPublisher.class,
null);
eventPublisherTracker.open();
scriptEngineTracker = new ServiceTracker<ScriptEngine, ScriptEngine>(bundleContext, ScriptEngine.class, null);
scriptEngineTracker.open();
}
/*
* (non-Javadoc)
*
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
@Override
public void stop(BundleContext bundleContext) throws Exception {
CompatibilityActivator.context = null;
itemRegistryTracker.close();
eventPublisherTracker.close();
scriptEngineTracker.close();
Audio.playStream(null);
}
}
@@ -0,0 +1,89 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.compat1x.internal;
import org.eclipse.smarthome.core.items.GroupItem;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.library.items.ColorItem;
import org.eclipse.smarthome.core.library.items.ContactItem;
import org.eclipse.smarthome.core.library.items.DateTimeItem;
import org.eclipse.smarthome.core.library.items.DimmerItem;
import org.eclipse.smarthome.core.library.items.NumberItem;
import org.eclipse.smarthome.core.library.items.RollershutterItem;
import org.eclipse.smarthome.core.library.items.StringItem;
import org.eclipse.smarthome.core.library.items.SwitchItem;
import org.eclipse.smarthome.core.types.State;
import org.openhab.core.items.GenericItem;
import org.openhab.library.tel.items.ESHCallItem;
public class ItemMapper {
public static org.openhab.core.items.Item mapToOpenHABItem(Item item) {
if (item==null) {
return null;
}
org.openhab.core.items.Item result = null;
Class<? extends Item> itemClass = item.getClass();
if (itemClass.equals(StringItem.class))
result = new org.openhab.core.library.items.StringItem(item.getName());
else if (itemClass.equals(SwitchItem.class))
result = new org.openhab.core.library.items.SwitchItem(item.getName());
else if (itemClass.equals(ContactItem.class))
result = new org.openhab.core.library.items.ContactItem(item.getName());
else if (itemClass.equals(NumberItem.class))
result = new org.openhab.core.library.items.NumberItem(item.getName());
else if (itemClass.equals(RollershutterItem.class))
result = new org.openhab.core.library.items.RollershutterItem(item.getName());
else if (itemClass.equals(DimmerItem.class))
result = new org.openhab.core.library.items.DimmerItem(item.getName());
else if (itemClass.equals(ColorItem.class))
result = new org.openhab.core.library.items.ColorItem(item.getName());
else if (itemClass.equals(DateTimeItem.class))
result = new org.openhab.core.library.items.DateTimeItem(item.getName());
else if (itemClass.equals(ESHCallItem.class))
result = new org.openhab.library.tel.items.CallItem(item.getName());
if (item instanceof GroupItem) {
GroupItem gItem = (GroupItem) item;
org.openhab.core.items.Item baseItem = ItemMapper.mapToOpenHABItem(gItem.getBaseItem());
org.openhab.core.items.GroupItem ohgItem;
if (baseItem instanceof GenericItem) {
ohgItem = new org.openhab.core.items.GroupItem(item.getName(), (GenericItem) baseItem);
} else {
ohgItem = new org.openhab.core.items.GroupItem(item.getName());
}
for (Item member : gItem.getMembers()) {
org.openhab.core.items.Item ohMember = ItemMapper.mapToOpenHABItem(member);
if (ohMember != null) {
ohgItem.addMember(ohMember);
}
}
result = ohgItem;
}
if (result instanceof org.openhab.core.items.GenericItem) {
org.openhab.core.items.GenericItem genericItem = (GenericItem) result;
State state = item.getState();
if (state != null) {
org.openhab.core.types.State ohState = (org.openhab.core.types.State) TypeMapper.mapToOpenHABType(state);
if (ohState != null) {
genericItem.setState(ohState);
}
}
}
return result;
}
}
@@ -0,0 +1,127 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.compat1x.internal;
import org.eclipse.smarthome.core.library.types.DateTimeType;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.HSBType;
import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.OpenClosedType;
import org.eclipse.smarthome.core.library.types.PercentType;
import org.eclipse.smarthome.core.library.types.PointType;
import org.eclipse.smarthome.core.library.types.StopMoveType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.library.types.UpDownType;
import org.eclipse.smarthome.core.types.Type;
import org.eclipse.smarthome.core.types.UnDefType;
public class TypeMapper {
public static org.openhab.core.types.Type mapToOpenHABType(Type type) {
if (type==null) {
return null;
}
org.openhab.core.types.Type result = org.openhab.core.types.UnDefType.UNDEF;
Class<? extends Type> typeClass = type.getClass();
if (type==UnDefType.NULL) {
result = org.openhab.core.types.UnDefType.NULL;
} else if (type==UnDefType.UNDEF) {
result = org.openhab.core.types.UnDefType.UNDEF;
} else if (type==OnOffType.ON) {
result = org.openhab.core.library.types.OnOffType.ON;
} else if (type==OnOffType.OFF) {
result = org.openhab.core.library.types.OnOffType.OFF;
} else if (type==OpenClosedType.OPEN) {
result = org.openhab.core.library.types.OpenClosedType.OPEN;
} else if (type==OpenClosedType.CLOSED) {
result = org.openhab.core.library.types.OpenClosedType.CLOSED;
} else if (type==IncreaseDecreaseType.INCREASE) {
result = org.openhab.core.library.types.IncreaseDecreaseType.INCREASE;
} else if (type==IncreaseDecreaseType.DECREASE) {
result = org.openhab.core.library.types.IncreaseDecreaseType.DECREASE;
} else if (type==StopMoveType.MOVE) {
result = org.openhab.core.library.types.StopMoveType.MOVE;
} else if (type==StopMoveType.STOP) {
result = org.openhab.core.library.types.StopMoveType.STOP;
} else if (type==UpDownType.UP) {
result = org.openhab.core.library.types.UpDownType.UP;
} else if (type==UpDownType.DOWN) {
result = org.openhab.core.library.types.UpDownType.DOWN;
} else if (typeClass.equals(StringType.class)) {
result = new org.openhab.core.library.types.StringType(type.toString());
} else if (typeClass.equals(DecimalType.class)) {
result = new org.openhab.core.library.types.DecimalType(type.toString());
} else if (typeClass.equals(HSBType.class)) {
result = new org.openhab.core.library.types.HSBType(type.toString());
} else if (typeClass.equals(PercentType.class)) {
result = new org.openhab.core.library.types.PercentType(type.toString());
} else if (typeClass.equals(DateTimeType.class)) {
result = new org.openhab.core.library.types.DateTimeType(type.toString());
} else if (typeClass.equals(PointType.class)) {
result = new org.openhab.core.library.types.PointType(type.toString());
}
return result;
}
public static Type mapToESHType(org.openhab.core.types.Type type) {
if (type==null) {
return null;
}
Type result = UnDefType.UNDEF;
Class<? extends org.openhab.core.types.Type> typeClass = type.getClass();
if (type==org.openhab.core.types.UnDefType.NULL) {
result = UnDefType.NULL;
} else if (type==org.openhab.core.types.UnDefType.UNDEF) {
result = UnDefType.UNDEF;
} else if (type==org.openhab.core.library.types.OnOffType.ON) {
result = OnOffType.ON;
} else if (type==org.openhab.core.library.types.OnOffType.OFF) {
result = OnOffType.OFF;
} else if (type==org.openhab.core.library.types.OpenClosedType.OPEN) {
result = OpenClosedType.OPEN;
} else if (type==org.openhab.core.library.types.OpenClosedType.CLOSED) {
result = OpenClosedType.CLOSED;
} else if (type==org.openhab.core.library.types.IncreaseDecreaseType.INCREASE) {
result = IncreaseDecreaseType.INCREASE;
} else if (type==org.openhab.core.library.types.IncreaseDecreaseType.DECREASE) {
result = IncreaseDecreaseType.DECREASE;
} else if (type==org.openhab.core.library.types.StopMoveType.MOVE) {
result = StopMoveType.MOVE;
} else if (type==org.openhab.core.library.types.StopMoveType.STOP) {
result = StopMoveType.STOP;
} else if (type==org.openhab.core.library.types.UpDownType.UP) {
result = UpDownType.UP;
} else if (type==org.openhab.core.library.types.UpDownType.DOWN) {
result = UpDownType.DOWN;
} else if (typeClass.equals(org.openhab.core.library.types.StringType.class)) {
result = new StringType(type.toString());
} else if (typeClass.equals(org.openhab.core.library.types.DecimalType.class)) {
result = new DecimalType(type.toString());
} else if (typeClass.equals(org.openhab.core.library.types.HSBType.class)) {
result = new HSBType(type.toString());
} else if (typeClass.equals(org.openhab.core.library.types.PercentType.class)) {
result = new PercentType(type.toString());
} else if (typeClass.equals(org.openhab.core.library.types.DateTimeType.class)) {
result = new DateTimeType(type.toString());
} else if (typeClass.equals(org.openhab.core.library.types.PointType.class)) {
result = new PointType(type.toString());
} else if (typeClass.equals(org.openhab.library.tel.types.CallType.class)) {
result = new org.openhab.library.tel.types.ESHCallType(type.toString());
}
return result;
}
}
@@ -0,0 +1,60 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events;
import static org.openhab.core.events.EventConstants.TOPIC_PREFIX;
import static org.openhab.core.events.EventConstants.TOPIC_SEPERATOR;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.EventType;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
abstract public class AbstractEventSubscriber implements EventHandler {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
String itemName = (String) event.getProperty("item");
String topic = event.getTopic();
String[] topicParts = topic.split(TOPIC_SEPERATOR);
if(!(topicParts.length > 2) || !topicParts[0].equals(TOPIC_PREFIX)) {
return; // we have received an event with an invalid topic
}
String operation = topicParts[1];
if(operation.equals(EventType.UPDATE.toString())) {
State newState = (State) event.getProperty("state");
if(newState!=null) receiveUpdate(itemName, newState);
}
if(operation.equals(EventType.COMMAND.toString())) {
Command command = (Command) event.getProperty("command");
if(command!=null) receiveCommand(itemName, command);
}
}
/**
* {@inheritDoc}
*/
public void receiveCommand(String itemName, Command command) {
// default implementation: do nothing
}
/**
* {@inheritDoc}
*/
public void receiveUpdate(String itemName, State newState) {
// default implementation: do nothing
}
}
@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events;
/**
* This interface defines constants required for using the OSGi Event Admin service.
*
* @author Kai Kreuzer
* @since 0.1.0
*/
public interface EventConstants {
public static final String TOPIC_PREFIX = "openhab";
public static final String TOPIC_SEPERATOR = "/";
}
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* An EventPublisher is used to send commands or status updates to the openHAB event bus.
*
* @author Kai Kreuzer
* @since 0.1.0
*/
public interface EventPublisher {
/**
* Initiate synchronous sending of a command.
* This method does not return to the caller until all subscribers have processed the command.
*
* @param itemName name of the item to send the command for
* @param command the command to send
*/
public abstract void sendCommand(String itemName, Command command);
/**
* Initiate asynchronous sending of a command.
* This method returns immediately to the caller.
*
* @param itemName name of the item to send the command for
* @param command the command to send
*/
public abstract void postCommand(String itemName, Command command);
/**
* Initiate asynchronous sending of a status update.
* This method returns immediately to the caller.
*
* @param itemName name of the item to send the update for
* @param newState the new state to send
*/
public abstract void postUpdate(String itemName, State newState);
}
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.items.events.ItemCommandEvent;
import org.eclipse.smarthome.core.items.events.ItemEventFactory;
import org.eclipse.smarthome.core.items.events.ItemStateEvent;
import org.openhab.core.compat1x.internal.TypeMapper;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EventPublisherDelegate implements org.openhab.core.events.EventPublisher {
private static final Logger logger = LoggerFactory.getLogger(EventPublisherDelegate.class);
private EventPublisher eventPublisher;
public void setEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void unsetEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = null;
}
@Override
public void sendCommand(String itemName, Command command) {
// we do not offer synchronous sending of commands anymore
postCommand(itemName, command);
}
@Override
public void postCommand(String itemName, Command command) {
org.eclipse.smarthome.core.types.Command eshCommand = (org.eclipse.smarthome.core.types.Command) TypeMapper.mapToESHType(command);
if(eshCommand!=null) {
ItemCommandEvent event = ItemEventFactory.createCommandEvent(itemName, eshCommand);
eventPublisher.post(event);
} else {
logger.warn("Compatibility layer could not convert {} of type {}.", command.toString(), command.getClass().getSimpleName() );
}
}
@Override
public void postUpdate(String itemName, State newState) {
org.eclipse.smarthome.core.types.State eshState = (org.eclipse.smarthome.core.types.State) TypeMapper.mapToESHType(newState);
if(eshState!=null) {
ItemStateEvent event = ItemEventFactory.createStateEvent(itemName, eshState);
eventPublisher.post(event);
} else {
logger.warn("Compatibility layer could not convert {} of type {}.", newState.toString(), newState.getClass().getSimpleName() );
}
}
}
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* An EventSubscriber receives events from the openHAB event bus for further processing.
*
* @author Kai Kreuzer
* @since 0.1.0
*/
public interface EventSubscriber {
/**
* Callback method if a command was sent on the event bus
*
* @param itemName the item for which a command was sent
* @param command the command that was sent
*/
public void receiveCommand(String itemName, Command command);
/**
* Callback method if a state update was sent on the event bus
*
* @param itemName the item for which a state update was sent
* @param state the state that was sent
*/
public void receiveUpdate(String itemName, State newStatus);
}
@@ -0,0 +1,145 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.events.internal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.smarthome.core.events.EventFilter;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.events.EventSubscriber;
import org.eclipse.smarthome.core.items.events.ItemCommandEvent;
import org.eclipse.smarthome.core.items.events.ItemEventFactory;
import org.eclipse.smarthome.core.items.events.ItemStateEvent;
import org.openhab.core.compat1x.internal.TypeMapper;
import org.openhab.core.types.Command;
import org.openhab.core.types.EventType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventHandler;
/**
* This class acts as a bridge between events from openHAB 1.x (using "openhab" as a topic prefix) and
* Eclipse SmartHome (using "smarthome" as a topic prefix).
* It simply duplicates events with an updated topic prefix and works both ways.
*
* @author Kai Kreuzer - Initial contribution and API
*
*/
public class EventBridge implements EventHandler, EventSubscriber {
private static final String BRIDGEMARKER = "bridgemarker";
private EventAdmin eventAdmin;
private EventPublisher eventPublisher;
public void setEventAdmin(EventAdmin eventAdmin) {
this.eventAdmin = eventAdmin;
}
public void unsetEventAdmin(EventAdmin eventAdmin) {
this.eventAdmin = null;
}
public void setEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void unsetEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = null;
}
@Override
public void handleEvent(Event event) {
if (!Boolean.TRUE.equals(event.getProperty(BRIDGEMARKER))) {
// map event from openHAB to ESH
if (event.getTopic().startsWith(org.openhab.core.events.EventConstants.TOPIC_PREFIX)) {
if (event.getTopic().endsWith(EventType.COMMAND.name())) {
String itemName = (String) event.getProperty("item");
Command ohCommand = (Command) event.getProperty("command");
ItemCommandEvent eshEvent = ItemEventFactory.createCommandEvent(itemName,
(org.eclipse.smarthome.core.types.Command) TypeMapper.mapToESHType(ohCommand));
eventPublisher.post(eshEvent);
} else if (event.getTopic().endsWith(EventType.UPDATE.name())) {
String itemName = (String) event.getProperty("item");
State ohState = (State) event.getProperty("state");
ItemStateEvent eshEvent = ItemEventFactory.createStateEvent(itemName,
(org.eclipse.smarthome.core.types.State) TypeMapper.mapToESHType(ohState));
eventPublisher.post(eshEvent);
}
}
}
}
private Map<String, Object> constructProperties(org.eclipse.smarthome.core.events.Event event) {
Map<String, Object> properties = new HashMap<>();
if (event instanceof ItemCommandEvent) {
ItemCommandEvent icEvent = (ItemCommandEvent) event;
String itemName = (String) icEvent.getItemName();
properties.put("item", itemName);
Type eshType = TypeMapper.mapToOpenHABType(icEvent.getItemCommand());
if (eshType instanceof Command) {
properties.put("command", (Command) eshType);
} else {
return null;
}
} else {
ItemStateEvent isEvent = (ItemStateEvent) event;
String itemName = (String) isEvent.getItemName();
properties.put("item", itemName);
Type eshType = TypeMapper.mapToOpenHABType(isEvent.getItemState());
if (eshType instanceof State) {
properties.put("state", (State) eshType);
} else {
return null;
}
}
properties.put(BRIDGEMARKER, true);
return properties;
}
@Override
public Set<String> getSubscribedEventTypes() {
Set<String> types = new HashSet<>(2);
types.add(ItemCommandEvent.TYPE);
types.add(ItemStateEvent.TYPE);
return types;
}
@Override
public EventFilter getEventFilter() {
return null;
}
@Override
public void receive(org.eclipse.smarthome.core.events.Event event) {
if (event.getType().equals(ItemCommandEvent.TYPE)) {
Map<String, Object> properties = constructProperties(event);
if (properties != null) {
String topic = org.openhab.core.events.EventConstants.TOPIC_PREFIX + "/" + EventType.COMMAND + "/"
+ properties.get("item");
eventAdmin.postEvent(new Event(topic, properties));
}
} else if (event.getType().equals(ItemStateEvent.TYPE)) {
Map<String, Object> properties = constructProperties(event);
if (properties != null) {
String topic = org.openhab.core.events.EventConstants.TOPIC_PREFIX + "/" + EventType.UPDATE + "/"
+ properties.get("item");
;
eventAdmin.postEvent(new Event(topic, properties));
}
}
}
}
@@ -0,0 +1,178 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* The abstract base class for all items. It provides all relevant logic
* for the infrastructure, such as publishing updates to the event bus
* or notifying listeners.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
abstract public class GenericItem implements Item {
protected EventPublisher eventPublisher;
protected Set<StateChangeListener> listeners = new CopyOnWriteArraySet<StateChangeListener>(Collections.newSetFromMap(new WeakHashMap<StateChangeListener, Boolean>()));
protected List<String> groupNames = new ArrayList<String>();
final protected String name;
protected State state = UnDefType.NULL;
public GenericItem(String name) {
this.name = name;
}
/**
* {@inheritDoc}
*/
public State getState() {
return state;
}
/**
* {@inheritDoc}
*/
public State getStateAs(Class<? extends State> typeClass) {
if(typeClass!=null && typeClass.isInstance(state)) {
return state;
} else {
return null;
}
}
public void initialize() {}
public void dispose() {
this.eventPublisher = null;
}
/**
* {@inheritDoc}
*/
public String getName() {
return name;
}
/**
* {@inheritDoc}
*/
public List<String> getGroupNames() {
return groupNames;
}
public void setEventPublisher(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
protected void internalSend(Command command) {
// try to send the command to the bus
if(eventPublisher!=null) {
eventPublisher.sendCommand(this.getName(), command);
}
}
public void setState(State state) {
State oldState = this.state;
this.state = state;
notifyListeners(oldState, state);
}
private void notifyListeners(State oldState, State newState) {
// if nothing has changed, we send update notifications
Set<StateChangeListener> clonedListeners = null;
clonedListeners = new CopyOnWriteArraySet<StateChangeListener>(listeners);
for(StateChangeListener listener : clonedListeners) {
listener.stateUpdated(this, newState);
}
if(!oldState.equals(newState)) {
for(StateChangeListener listener : clonedListeners) {
listener.stateChanged(this, oldState, newState);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return getName() + " (" +
"Type=" + getClass().getSimpleName() + ", " +
"State=" + getState() + ")";
}
public void addStateChangeListener(StateChangeListener listener) {
synchronized(listeners) {
listeners.add(listener);
}
}
public void removeStateChangeListener(StateChangeListener listener) {
synchronized(listeners) {
listeners.remove(listener);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((groupNames == null) ? 0 : groupNames.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GenericItem other = (GenericItem) obj;
if (groupNames == null) {
if (other.groupNames != null)
return false;
} else if (!groupNames.equals(other.groupNames))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (state == null) {
if (other.state != null)
return false;
} else if (!state.equals(other.state))
return false;
return true;
}
}
@@ -0,0 +1,84 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.List;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* Group functions are used by active group items to calculate a state for the group
* out of the states of all its member items.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
abstract public interface GroupFunction {
/**
* Determines the current state of a group based on a list of items
*
* @param items the items to calculate a group state for
* @return the calculated group state
*/
public State calculate(List<Item> items);
/**
* Calculates the group state and returns it as a state of the requested type.
*
* @param items the items to calculate a group state for
* @param stateClass the type in which the state should be returned
* @return the calculated group state of the requested type or null, if type is not supported
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass);
/**
* This is the default group function that does nothing else than to check if all member items
* have the same state. If this is the case, this state is returned, otherwise UNDEF is returned.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
static class Equality implements GroupFunction {
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
if(items.size()>0) {
State state = items.get(0).getState();
for(int i=1; i<items.size(); i++) {
if(!state.equals(items.get(i).getState())) {
return UnDefType.UNDEF;
}
}
return state;
} else {
return UnDefType.UNDEF;
}
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items,
Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
return null;
}
}
}
}
@@ -0,0 +1,222 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.collections.ListUtils;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GroupItem extends GenericItem implements StateChangeListener {
private static final Logger logger = LoggerFactory.getLogger(GroupItem.class);
protected final GenericItem baseItem;
protected final List<Item> members;
protected GroupFunction function;
public GroupItem(String name) {
this(name, null);
}
public GroupItem(String name, GenericItem baseItem) {
this(name, baseItem, new GroupFunction.Equality());
}
public GroupItem(String name, GenericItem baseItem, GroupFunction function) {
super(name);
members = new CopyOnWriteArrayList<Item>();
this.function = function;
this.baseItem = baseItem;
}
/**
* Returns the base item of this {@link GroupItem}. This method is only
* intended to allow instance checks of the underlying BaseItem. It must
* not be changed in any way.
*
* @return the base item of this GroupItem
*/
public GenericItem getBaseItem() {
return baseItem;
}
/**
* Returns the direct members of this {@link GroupItem} regardless if these
* members are {@link GroupItem}s as well.
*
* @return the direct members of this {@link GroupItem}
*/
public List<Item> getMembers() {
return members;
}
/**
* Returns the direct members of this {@link GroupItem} and recursively all
* members of the potentially contained {@link GroupItem}s as well. The
* {@link GroupItem}s itself aren't contained. The returned items are unique.
*
* @return all members of this and all contained {@link GroupItem}s
*/
public List<Item> getAllMembers() {
Set<Item> allMembers = new HashSet<Item>();
collectMembers(allMembers, members);
return new ArrayList<Item>(allMembers);
}
private void collectMembers(Set<Item> allMembers, List<Item> members) {
for (Item member : members) {
if (member instanceof GroupItem) {
collectMembers(allMembers, ((GroupItem) member).members);
}
else {
allMembers.add(member);
}
}
}
public void addMember(Item item) {
members.add(item);
if (item instanceof GenericItem) {
GenericItem genericItem = (GenericItem) item;
genericItem.addStateChangeListener(this);
}
}
public void removeMember(Item item) {
members.remove(item);
if (item instanceof GenericItem) {
GenericItem genericItem = (GenericItem) item;
genericItem.removeStateChangeListener(this);
}
}
/**
* The accepted data types of a group item is the same as of the underlying base item.
* If none is defined, the intersection of all sets of accepted data types of all group
* members is used instead.
*
* @return the accepted data types of this group item
*/
@SuppressWarnings("unchecked")
public List<Class<? extends State>> getAcceptedDataTypes() {
if(baseItem!=null) {
return baseItem.getAcceptedDataTypes();
} else {
List<Class<? extends State>> acceptedDataTypes = null;
for(Item item : members) {
if(acceptedDataTypes==null) {
acceptedDataTypes = item.getAcceptedDataTypes();
} else {
acceptedDataTypes = ListUtils.intersection(acceptedDataTypes, item.getAcceptedDataTypes());
}
}
return acceptedDataTypes == null ? ListUtils.EMPTY_LIST : acceptedDataTypes;
}
}
/**
* The accepted command types of a group item is the same as of the underlying base item.
* If none is defined, the intersection of all sets of accepted command types of all group
* members is used instead.
*
* @return the accepted command types of this group item
*/
@SuppressWarnings("unchecked")
public List<Class<? extends Command>> getAcceptedCommandTypes() {
if(baseItem!=null) {
return baseItem.getAcceptedCommandTypes();
} else {
List<Class<? extends Command>> acceptedCommandTypes = null;
for(Item item : members) {
if(acceptedCommandTypes==null) {
acceptedCommandTypes = item.getAcceptedCommandTypes();
} else {
acceptedCommandTypes = ListUtils.intersection(acceptedCommandTypes, item.getAcceptedCommandTypes());
}
}
return acceptedCommandTypes == null ? ListUtils.EMPTY_LIST : acceptedCommandTypes;
}
}
public void send(Command command) {
if(getAcceptedCommandTypes().contains(command.getClass())) {
internalSend(command);
} else {
logger.warn("Command '{}' has been ignored for group '{}' as it is not accepted.", command.toString(), getName());
}
}
/**
* @{inheritDoc
*/
@Override
protected void internalSend(Command command) {
if(eventPublisher!=null) {
for(Item member : members) {
// try to send the command to the bus
eventPublisher.sendCommand(member.getName(), command);
}
}
}
/**
* @{inheritDoc
*/
@Override
public State getStateAs(Class<? extends State> typeClass) {
State newState = function.getStateAs(getAllMembers(), typeClass);
if(newState==null && baseItem!=null) {
// we use the transformation method from the base item
baseItem.setState(state);
newState = baseItem.getStateAs(typeClass);
}
if(newState==null) {
newState = super.getStateAs(typeClass);
}
return newState;
}
/**
* @{inheritDoc
*/
@Override
public String toString() {
return getName() + " (" +
"Type=" + getClass().getSimpleName() + ", " +
(baseItem != null ? "BaseType=" + baseItem.getClass().getSimpleName() + ", " : "") +
"Members=" + members.size() + ", " +
"State=" + getState() + ")";
}
/**
* @{inheritDoc
*/
public void stateChanged(Item item, State oldState, State newState) {
setState(function.calculate(members));
}
/**
* @{inheritDoc
*/
public void stateUpdated(Item item, State state) {
setState(function.calculate(members));
}
}
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.List;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
/**
* <p>This interface defines the core features of an openHAB item.</p>
* <p>Item instances are used for all stateful services and are especially
* important for the {@link ItemRegistry}.</p>
*
* @author Kai Kreuzer
*
*/
public interface Item {
/**
* returns the current state of the item
*
* @return the current state
*/
public State getState();
/**
* returns the current state of the item as a specific type
*
* @return the current state in the requested type or
* null, if state cannot be provided as the requested type
*/
public State getStateAs(Class<? extends State> typeClass);
/**
* returns the name of the item
*
* @return the name of the item
*/
public String getName();
/**
* <p>This method provides a list of all data types that can be used to update the item state</p>
* <p>Imagine e.g. a dimmer device: It's status could be 0%, 10%, 50%, 100%, but also OFF or ON and
* maybe UNDEFINED. So the accepted data types would be in this case {@link PercentType}, {@link OnOffType}
* and {@link UnDefType}</p>
*
* @return a list of data types that can be used to update the item state
*/
public List<Class<? extends State>> getAcceptedDataTypes();
/**
* <p>This method provides a list of all command types that can be used for this item</p>
* <p>Imagine e.g. a dimmer device: You could ask it to dim to 0%, 10%, 50%, 100%, but
* also to turn OFF or ON. So the accepted command types would be in this case {@link PercentType},
* {@link OnOffType}</p>
*
* @return a list of all command types that can be used for this item
*/
public List<Class<? extends Command>> getAcceptedCommandTypes();
/**
* Returns a list of the names of the groups this item belongs to.
*
* @return list of item group names
*/
public List<String> getGroupNames();
}
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
/**
* This Factory creates concrete instances of the known ItemTypes.
*
* @author Thomas.Eichstaedt-Engelen
* @since 0.9.0
*/
public interface ItemFactory {
/**
* Creates a new Item instance of type <code>itemTypeName</code> and the name
* <code>itemName</code>
*
* @param itemTypeName
* @param itemName
*
* @return a new Item of type <code>itemTypeName</code> or
* <code>null</code> if no matching class is known.
*/
GenericItem createItem(String itemTypeName, String itemName);
/**
* Returns the list of all supported ItemTypes of this Factory.
*
* @return the supported ItemTypes
*/
String[] getSupportedItemTypes();
}
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
/**
* This is an abstract parent exception to be extended by any exceptions
* related to item lookups in the item registry.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public abstract class ItemLookupException extends Exception {
public ItemLookupException(String string) {
super(string);
}
private static final long serialVersionUID = -4617708589675048859L;
}
@@ -0,0 +1,26 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
/**
* This exception is thrown by the {@link ItemRegistry} if an item could
* not be found.
*
* @author Kai Kreuzer
*
*/
public class ItemNotFoundException extends ItemLookupException {
public ItemNotFoundException(String name) {
super("Item '" + name + "' could not be found in the item registry");
}
private static final long serialVersionUID = -3720784568250902711L;
}
@@ -0,0 +1,41 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.Collection;
/**
* This exception can be thrown whenever a search pattern does not uniquely identify
* an item. The list of matching items must be made available through this exception.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class ItemNotUniqueException extends ItemLookupException {
private static final long serialVersionUID = 5154625234283910124L;
private final Collection<Item> matchingItems;
public ItemNotUniqueException(String string, Collection<Item> items) {
super("Item cannot be uniquely identified by '" + string + "'");
this.matchingItems = items;
}
/**
* Returns all items that match the search pattern
*
* @return collection of items matching the search pattern
*/
public Collection<Item> getMatchingItems() {
return matchingItems;
}
}
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.Collection;
/**
* An item provider provides instances of {@link GenericItem}. These
* items can be constructed from some static configuration files or
* they can be derived from some dynamic logic.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public interface ItemProvider {
/**
* Provides an array of items.
*
* @return a collection of items
*/
Collection<Item> getItems();
public void addItemChangeListener(ItemsChangeListener listener);
public void removeItemChangeListener(ItemsChangeListener listener);
}
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.Collection;
/**
* The ItemRegistry is the central place, where items are kept in memory and their state
* is permanently tracked. So any code that requires the current state of items should use
* this service (instead of trying to keep their own local copy of the items).
*
* Items are registered by {@link ItemProvider}s, which can provision them from any source
* they like and also dynamically remove or add items.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public interface ItemRegistry {
/**
* This method retrieves a single item from the registry.
*
* @param name the item name
* @return the uniquely identified item
* @throws ItemNotFoundException if no item matches the input
*/
public Item getItem(String name) throws ItemNotFoundException;
/**
* This method retrieves a single item from the registry.
* Search patterns and shortened versions are supported, if they uniquely identify an item
*
* @param name the item name, a part of the item name or a search pattern
* @return the uniquely identified item
* @throws ItemNotFoundException if no item matches the input
* @throws ItemNotUniqueException if multiply items match the input
*/
public Item getItemByPattern(String name) throws ItemNotFoundException, ItemNotUniqueException;
/**
* This method retrieves all items that are currently available in the registry
*
* @return a collection of all available items
*/
public Collection<Item> getItems();
/**
* This method retrieves all items that match a given search pattern
*
* @return a collection of all items matching the search pattern
*/
public Collection<Item> getItems(String pattern);
/**
* Checks whether itemName matches the item name conventions.
* Item names must only consist out of alpha-numerical characters and
* underscores (_).
*
* @param itemName the item name to validate
* @return true, if the name is valid
*/
public boolean isValidItemName(String itemName);
public void addItemRegistryChangeListener(ItemRegistryChangeListener listener);
public void removeItemRegistryChangeListener(ItemRegistryChangeListener listener);
}
@@ -0,0 +1,44 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.Collection;
/**
* This is a listener interface which should be implemented where ever the item registry is
* used in order to be notified of any dynamic changes in the provided items.
*
* @author Kai Kreuzer
* @since 0.4.0
*
*/
public interface ItemRegistryChangeListener {
/**
* Notifies the listener that all items in the registry have changed and thus should be reloaded.
*
* @param oldItemNames a collection of all previous item names, so that references can be removed
*/
public void allItemsChanged(Collection<String> oldItemNames);
/**
* Notifies the listener that a single item has been added
*
* @param item the item that has been added
*/
public void itemAdded(Item item);
/**
* Notifies the listener that a single item has been removed
*
* @param item the item that has been removed
*/
public void itemRemoved(Item item);
}
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import java.util.Collection;
/**
* This is a listener interface which should be implemented where ever item providers or
* the item registry are used in order to be notified of any dynamic changes in the provided items.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public interface ItemsChangeListener {
/**
* Notifies the listener that all items of a provider have changed and thus should be reloaded.
*
* @param provider the concerned item provider
* @param oldItemNames a collection of all previous item names, so that references can be removed
*/
public void allItemsChanged(ItemProvider provider, Collection<String> oldItemNames);
/**
* Notifies the listener that a single item has been added
*
* @param provider the concerned item provider
* @param item the item that has been added
*/
public void itemAdded(ItemProvider provider, Item item);
/**
* Notifies the listener that a single item has been removed
*
* @param provider the concerned item provider
* @param item the item that has been removed
*/
public void itemRemoved(ItemProvider provider, Item item);
}
@@ -0,0 +1,41 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items;
import org.openhab.core.types.State;
/**
* <p>This interface must be implemented by all classes that want to be notified
* about changes in the state of an item.</p>
* <p>The {@link GenericItem} class provides the possibility to register such
* listeners.</p>
*
* @author Kai Kreuzer
*
*/
public interface StateChangeListener {
/**
* This method is called, if a state has changed.
*
* @param item the item whose state has changed
* @param oldState the previous state
* @param newState the new state
*/
public void stateChanged(Item item, State oldState, State newState);
/**
* This method is called, if a state was updated, but has not changed
*
* @param item the item whose state was updated
* @param state the current state, same before and after the update
*/
public void stateUpdated(Item item, State state);
}
@@ -0,0 +1,209 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.items.internal;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.smarthome.core.common.registry.RegistryChangeListener;
import org.openhab.core.compat1x.internal.ItemMapper;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemNotFoundException;
import org.openhab.core.items.ItemNotUniqueException;
import org.openhab.core.items.ItemRegistryChangeListener;
import org.openhab.core.types.State;
import org.openhab.model.sitemap.LinkableWidget;
import org.openhab.model.sitemap.Sitemap;
import org.openhab.model.sitemap.Widget;
import org.openhab.ui.items.ItemUIRegistry;
public class ItemUIRegistryDelegate
implements ItemUIRegistry, RegistryChangeListener<org.eclipse.smarthome.core.items.Item> {
private org.eclipse.smarthome.ui.items.ItemUIRegistry itemUIRegistry;
private Set<ItemRegistryChangeListener> listeners = new HashSet<>();
protected void setItemUIRegistry(org.eclipse.smarthome.ui.items.ItemUIRegistry itemUIRegistry) {
this.itemUIRegistry = itemUIRegistry;
itemUIRegistry.addRegistryChangeListener(this);
}
protected void unsetItemUIRegistry(org.eclipse.smarthome.core.items.ItemRegistry itemUIRegistry) {
this.itemUIRegistry = null;
}
@Override
public Item getItem(String name) throws ItemNotFoundException {
org.eclipse.smarthome.core.items.Item eshItem;
try {
eshItem = itemUIRegistry.getItem(name);
} catch (org.eclipse.smarthome.core.items.ItemNotFoundException e) {
throw new ItemNotFoundException(name);
}
return ItemMapper.mapToOpenHABItem(eshItem);
}
@Override
public Item getItemByPattern(String name) throws ItemNotFoundException, ItemNotUniqueException {
org.eclipse.smarthome.core.items.Item eshItem;
try {
eshItem = itemUIRegistry.getItemByPattern(name);
} catch (org.eclipse.smarthome.core.items.ItemNotFoundException e) {
throw new ItemNotFoundException(name);
} catch (org.eclipse.smarthome.core.items.ItemNotUniqueException e) {
throw new ItemNotUniqueException(name, null);
}
return ItemMapper.mapToOpenHABItem(eshItem);
}
@Override
public Collection<Item> getItems() {
Collection<org.eclipse.smarthome.core.items.Item> eshItems = itemUIRegistry.getItems();
Collection<Item> ohItems = new HashSet<Item>(eshItems.size());
for (org.eclipse.smarthome.core.items.Item eshItem : eshItems) {
ohItems.add(ItemMapper.mapToOpenHABItem(eshItem));
}
return ohItems;
}
@Override
public Collection<Item> getItems(String pattern) {
Collection<org.eclipse.smarthome.core.items.Item> eshItems = itemUIRegistry.getItems(pattern);
Collection<Item> ohItems = new HashSet<Item>(eshItems.size());
for (org.eclipse.smarthome.core.items.Item eshItem : eshItems) {
ohItems.add(ItemMapper.mapToOpenHABItem(eshItem));
}
return ohItems;
}
@Override
public boolean isValidItemName(String itemName) {
return itemUIRegistry.isValidItemName(itemName);
}
@Override
public void addItemRegistryChangeListener(ItemRegistryChangeListener listener) {
this.listeners.add(listener);
}
@Override
public void removeItemRegistryChangeListener(ItemRegistryChangeListener listener) {
this.listeners.remove(listener);
}
@Override
public void added(org.eclipse.smarthome.core.items.Item element) {
Item ohItem = ItemMapper.mapToOpenHABItem(element);
for (ItemRegistryChangeListener listener : listeners) {
listener.itemAdded(ohItem);
}
}
@Override
public void removed(org.eclipse.smarthome.core.items.Item element) {
Item ohItem = ItemMapper.mapToOpenHABItem(element);
for (ItemRegistryChangeListener listener : listeners) {
listener.itemRemoved(ohItem);
}
}
@Override
public void updated(org.eclipse.smarthome.core.items.Item oldElement,
org.eclipse.smarthome.core.items.Item element) {
Item ohItem = ItemMapper.mapToOpenHABItem(element);
for (ItemRegistryChangeListener listener : listeners) {
listener.itemRemoved(ohItem);
listener.itemAdded(ohItem);
}
}
@Override
public String getIcon(String itemName) {
return itemUIRegistry.getCategory(itemName);
}
@Override
public String getLabel(String itemName) {
return itemUIRegistry.getLabel(itemName);
}
@Override
public Widget getDefaultWidget(Class<? extends Item> itemType, String itemName) {
return null;
}
@Override
public Widget getWidget(String itemName) {
return null;
}
@Override
public String getLabel(Widget w) {
return itemUIRegistry.getLabel(w.getItem());
}
@Override
public String getIcon(Widget w) {
return itemUIRegistry.getCategory(w.getItem());
}
@Override
public State getState(Widget w) {
return null;
}
@Override
public Widget getWidget(Sitemap sitemap, String id) {
return null;
}
@Override
public String getWidgetId(Widget w) {
return null;
}
@Override
public EList<Widget> getChildren(LinkableWidget w) {
return null;
}
@Override
public boolean iconExists(String icon) {
return true;
}
@Override
public String getLabelColor(Widget w) {
return null;
}
@Override
public String getValueColor(Widget w) {
return null;
}
@Override
public boolean getVisiblity(Widget w) {
return true;
}
@Override
public State getItemState(String itemName) {
try {
return getItem(itemName).getState();
} catch (ItemNotFoundException e) {
return null;
}
}
}
@@ -0,0 +1,119 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A ColorItem can be used for color values, e.g. for LED lights
*
* @author Kai Kreuzer
* @since 1.2.0
*
*/public class ColorItem extends DimmerItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(OnOffType.class);
acceptedDataTypes.add(PercentType.class);
acceptedDataTypes.add(HSBType.class);
acceptedDataTypes.add(UnDefType.class);
acceptedCommandTypes.add(OnOffType.class);
acceptedCommandTypes.add(IncreaseDecreaseType.class);
acceptedCommandTypes.add(PercentType.class);
acceptedCommandTypes.add(HSBType.class);
}
public ColorItem(String name) {
super(name);
}
public void send(HSBType command) {
internalSend(command);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
/**
* {@inheritDoc}
*/
@Override
public void setState(State state) {
State currentState = this.state;
if(currentState instanceof HSBType) {
DecimalType hue = ((HSBType) currentState).getHue();
PercentType saturation = ((HSBType) currentState).getSaturation();
// we map ON/OFF values to dark/bright, so that the hue and saturation values are not changed
if(state==OnOffType.OFF) {
super.setState(new HSBType(hue, saturation, PercentType.ZERO));
} else if(state==OnOffType.ON) {
super.setState(new HSBType(hue, saturation, PercentType.HUNDRED));
} else if(state instanceof PercentType && !(state instanceof HSBType)) {
super.setState(new HSBType(hue, saturation, (PercentType) state));
} else {
super.setState(state);
}
} else {
// we map ON/OFF values to black/white and percentage values to grey scale
if(state==OnOffType.OFF) {
super.setState(HSBType.BLACK);
} else if(state==OnOffType.ON) {
super.setState(HSBType.WHITE);
} else if(state instanceof PercentType && !(state instanceof HSBType)) {
super.setState(new HSBType(DecimalType.ZERO, PercentType.ZERO, (PercentType) state));
} else {
super.setState(state);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public State getStateAs(Class<? extends State> typeClass) {
if(typeClass==HSBType.class) {
return this.state;
} else if(typeClass==OnOffType.class) {
if(state instanceof HSBType) {
HSBType hsbState = (HSBType) state;
// if brightness is not completely off, we consider the state to be on
return hsbState.getBrightness().equals(PercentType.ZERO) ? OnOffType.OFF : OnOffType.ON;
}
} else if(typeClass==DecimalType.class) {
if(state instanceof HSBType) {
HSBType hsbState = (HSBType) state;
return new DecimalType(hsbState.getBrightness().toBigDecimal().divide(new BigDecimal(100), 8, RoundingMode.UP));
}
}
return super.getStateAs(typeClass);
}
}
@@ -0,0 +1,69 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A ContactItem can be used for sensors that return an "open" or "close" as a state.
* This is useful for doors, windows, etc.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class ContactItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(OpenClosedType.class);
acceptedDataTypes.add(UnDefType.class);
}
public ContactItem(String name) {
super(name);
}
public void send(OpenClosedType command) {
internalSend(command);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
/**
* {@inheritDoc}
*/
@Override
public State getStateAs(Class<? extends State> typeClass) {
if(typeClass==DecimalType.class) {
return state==OpenClosedType.OPEN ? new DecimalType(1) : DecimalType.ZERO;
} else if(typeClass==PercentType.class) {
return state==OpenClosedType.OPEN ? PercentType.HUNDRED : PercentType.ZERO;
} else {
return super.getStateAs(typeClass);
}
}
}
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A DateTimeItem stores a timestamp including a valid time zone.
*
* @author Thomas.Eichstaedt-Engelen
* @author Kai Kreuzer
*
* @since 0.8.0
*/
public class DateTimeItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add((DateTimeType.class));
acceptedDataTypes.add(UnDefType.class);
}
public DateTimeItem(String name) {
super(name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
}
@@ -0,0 +1,93 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A DimmerItem can be used as a switch (ON/OFF), but it also accepts percent values
* to reflect the dimmed state.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class DimmerItem extends SwitchItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(OnOffType.class);
acceptedDataTypes.add(PercentType.class);
acceptedDataTypes.add(UnDefType.class);
acceptedCommandTypes.add(OnOffType.class);
acceptedCommandTypes.add(IncreaseDecreaseType.class);
acceptedCommandTypes.add(PercentType.class);
}
public DimmerItem(String name) {
super(name);
}
public void send(PercentType command) {
internalSend(command);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
/**
* {@inheritDoc}
*/
@Override
public void setState(State state) {
// we map ON/OFF values to the percent values 0 and 100
if(state==OnOffType.OFF) {
super.setState(PercentType.ZERO);
} else if(state==OnOffType.ON) {
super.setState(PercentType.HUNDRED);
} else {
super.setState(state);
}
}
/**
* {@inheritDoc}
*/
@Override
public State getStateAs(Class<? extends State> typeClass) {
if(typeClass==OnOffType.class) {
// if it is not completely off, we consider the dimmer to be on
return state.equals(PercentType.ZERO) ? OnOffType.OFF : OnOffType.ON;
} else if(typeClass==DecimalType.class) {
if(state instanceof PercentType) {
return new DecimalType(((PercentType) state).toBigDecimal().divide(new BigDecimal(100), 8, RoundingMode.UP));
}
}
return super.getStateAs(typeClass);
}
}
@@ -0,0 +1,73 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PointType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A LocationItem can be used to store GPS related informations, addresses...
* This is useful for location awareness related functions
*
* @author Gaël L'hopital
* @since 1.7.0
*/
public class LocationItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(PointType.class);
acceptedDataTypes.add(UnDefType.class);
}
public LocationItem(String name) {
super(name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
/**
* Compute the distance with another Point type,
* http://stackoverflow.com/questions/837872/calculate-distance-in-meters-when-you-know-longitude-and-latitude-in-java
* @return distance between the two points in meters
*/
public DecimalType distanceFrom(PointType away){
double dist = -1;
if ((away != null) && (this.state instanceof PointType)) {
PointType me = (PointType) this.state;
double dLat = Math.pow(Math.sin(Math.toRadians(away.getLatitude().doubleValue() - me.getLatitude().doubleValue()) / 2),2);
double dLng = Math.pow(Math.sin(Math.toRadians(away.getLongitude().doubleValue() - me.getLongitude().doubleValue()) / 2),2);
double a = dLat + Math.cos(Math.toRadians(me.getLatitude().doubleValue()))
* Math.cos(Math.toRadians(away.getLatitude().doubleValue())) * dLng;
dist = PointType.WGS84_a * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
}
return new DecimalType(dist);
}
}
@@ -0,0 +1,53 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A NumberItem has a decimal value and is usually used for all kinds
* of sensors, like temperature, brightness, wind, etc.
* It can also be used as a counter or as any other thing that can be expressed
* as a number.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class NumberItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(DecimalType.class);
acceptedDataTypes.add(UnDefType.class);
acceptedCommandTypes.add(DecimalType.class);
}
public NumberItem(String name) {
super(name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
}
@@ -0,0 +1,95 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A RollershutterItem allows the control of roller shutters, i.e.
* moving them up, down, stopping or setting it to close to a certain percentage.
*
* @author Kai Kreuzer
*
*/
public class RollershutterItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(UnDefType.class);
acceptedDataTypes.add(UpDownType.class);
acceptedDataTypes.add(PercentType.class);
acceptedCommandTypes.add(UpDownType.class);
acceptedCommandTypes.add(StopMoveType.class);
acceptedCommandTypes.add(PercentType.class);
}
public RollershutterItem(String name) {
super(name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
/**
* {@inheritDoc}
*/
@Override
public void setState(State state) {
// we map UP/DOWN values to the percent values 0 and 100
if(state==UpDownType.UP) {
super.setState(PercentType.ZERO);
} else if(state==UpDownType.DOWN) {
super.setState(PercentType.HUNDRED);
} else {
super.setState(state);
}
}
/**
* {@inheritDoc}
*/
@Override
public State getStateAs(Class<? extends State> typeClass) {
if(typeClass==UpDownType.class) {
if(state.equals(PercentType.ZERO)) {
return UpDownType.UP;
} else if(state.equals(PercentType.HUNDRED)) {
return UpDownType.DOWN;
} else {
return UnDefType.UNDEF;
}
} else if(typeClass==DecimalType.class) {
if(state instanceof PercentType) {
return new DecimalType(((PercentType) state).toBigDecimal().divide(new BigDecimal(100), 8, RoundingMode.UP));
}
}
return super.getStateAs(typeClass);
}
}
@@ -0,0 +1,66 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.TypeParser;
import org.openhab.core.types.UnDefType;
/**
* A StringItem can be used for any kind of string to either send or receive
* from a device.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class StringItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(StringType.class);
acceptedDataTypes.add((DateTimeType.class));
acceptedDataTypes.add(UnDefType.class);
acceptedCommandTypes.add(StringType.class);
}
public StringItem(String name) {
super(name);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
@Override
public State getStateAs(Class<? extends State> typeClass) {
ArrayList<Class<? extends State>> list = new ArrayList<Class<? extends State>>();
list.add(typeClass);
State convertedState = TypeParser.parseState(list, state.toString());
if(convertedState!=null) {
return convertedState;
} else {
return super.getStateAs(typeClass);
}
}
}
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.items;
import java.util.ArrayList;
import java.util.List;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* A SwitchItem represents a normal switch that can be ON or OFF.
* Useful for normal lights, presence detection etc.
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class SwitchItem extends GenericItem {
private static List<Class<? extends State>> acceptedDataTypes = new ArrayList<Class<? extends State>>();
private static List<Class<? extends Command>> acceptedCommandTypes = new ArrayList<Class<? extends Command>>();
static {
acceptedDataTypes.add(OnOffType.class);
acceptedDataTypes.add(UnDefType.class);
acceptedCommandTypes.add(OnOffType.class);
}
public SwitchItem(String name) {
super(name);
}
public void send(OnOffType command) {
internalSend(command);
}
public List<Class<? extends State>> getAcceptedDataTypes() {
return acceptedDataTypes;
}
public List<Class<? extends Command>> getAcceptedCommandTypes() {
return acceptedCommandTypes;
}
@Override
public State getStateAs(Class<? extends State> typeClass) {
if(typeClass==DecimalType.class) {
return state==OnOffType.ON ? new DecimalType(1) : DecimalType.ZERO;
} else if(typeClass==PercentType.class) {
return state==OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO;
} else {
return super.getStateAs(typeClass);
}
}
}
@@ -0,0 +1,397 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import org.openhab.core.items.GroupFunction;
import org.openhab.core.items.Item;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/**
* This interface is only a container for functions that require the core type library
* for its calculations.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
public interface ArithmeticGroupFunction extends GroupFunction {
/**
* This does a logical 'and' operation. Only if all items are of 'activeState' this
* is returned, otherwise the 'passiveState' is returned.
*
* Through the getStateAs() method, it can be determined, how many
* items actually are not in the 'activeState'.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
static class And implements GroupFunction {
protected final State activeState;
protected final State passiveState;
public And(State activeValue, State passiveValue) {
if(activeValue==null || passiveValue==null) {
throw new IllegalArgumentException("Parameters must not be null!");
}
this.activeState = activeValue;
this.passiveState = passiveValue;
}
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
if(items!=null && items.size()>0) {
for(Item item : items) {
if(!activeState.equals(item.getState())) {
return passiveState;
}
}
return activeState;
} else {
// if we do not have any items, we return the passive state
return passiveState;
}
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
if(stateClass == DecimalType.class) {
if(items!=null) {
return new DecimalType(items.size() - count(items, activeState));
} else {
return DecimalType.ZERO;
}
} else {
return null;
}
}
}
private int count(List<Item> items, State state) {
int count = 0;
if(items!=null && state!=null) {
for(Item item : items) {
if(state.equals(item.getStateAs(state.getClass()))) {
count++;
}
}
}
return count;
}
}
/**
* This does a logical 'or' operation. If at least one item is of 'activeState' this
* is returned, otherwise the 'passiveState' is returned.
*
* Through the getStateAs() method, it can be determined, how many
* items actually are in the 'activeState'.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
static class Or implements GroupFunction {
protected final State activeState;
protected final State passiveState;
public Or(State activeValue, State passiveValue) {
if(activeValue==null || passiveValue==null) {
throw new IllegalArgumentException("Parameters must not be null!");
}
this.activeState = activeValue;
this.passiveState = passiveValue;
}
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
if(items!=null) {
for(Item item : items) {
if(activeState.equals(item.getState())) {
return activeState;
}
}
}
return passiveState;
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
if(stateClass == DecimalType.class) {
return new DecimalType(count(items, activeState));
} else {
return null;
}
}
}
private int count(List<Item> items, State state) {
int count = 0;
if(items!=null && state!=null) {
for(Item item : items) {
if(state.equals(item.getStateAs(state.getClass()))) {
count++;
}
}
}
return count;
}
}
/**
* This does a logical 'nand' operation. The state is 'calculated' by
* the normal 'and' operation and than negated by returning the opposite
* value. E.g. when the 'and' operation calculates the activeValue the
* passiveValue will be returned and vice versa.
*
* @author Thomas.Eichstaedt-Engelen
* @since 1.0.0
*/
static class NAnd extends And {
public NAnd(State activeValue, State passiveValue) {
super(activeValue, passiveValue);
}
public State calculate(List<Item> items) {
State result = super.calculate(items);
State notResult =
result.equals(activeState) ? passiveState : activeState;
return notResult;
}
}
/**
* This does a logical 'nor' operation. The state is 'calculated' by
* the normal 'or' operation and than negated by returning the opposite
* value. E.g. when the 'or' operation calculates the activeValue the
* passiveValue will be returned and vice versa.
*
* @author Thomas.Eichstaedt-Engelen
* @since 1.0.0
*/
static class NOr extends Or {
public NOr(State activeValue, State passiveValue) {
super(activeValue, passiveValue);
}
public State calculate(List<Item> items) {
State result = super.calculate(items);
State notResult =
result.equals(activeState) ? passiveState : activeState;
return notResult;
}
}
/**
* This calculates the numeric average over all item states of decimal type.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
static class Avg implements GroupFunction {
public Avg() {}
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
BigDecimal sum = BigDecimal.ZERO;
int count = 0;
if(items!=null) {
for(Item item : items) {
DecimalType itemState = (DecimalType) item.getStateAs(DecimalType.class);
if(itemState!=null) {
sum = sum.add(itemState.toBigDecimal());
count++;
}
}
}
if(count>0) {
return new DecimalType(sum.divide(new BigDecimal(count), RoundingMode.HALF_UP));
} else {
return UnDefType.UNDEF;
}
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
return null;
}
}
}
/**
* This calculates the numeric sum over all item states of decimal type.
*
* @author Thomas.Eichstaedt-Engelen
* @since 1.1.0
*
*/
static class Sum implements GroupFunction {
public Sum() {}
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
BigDecimal sum = BigDecimal.ZERO;
if(items!=null) {
for(Item item : items) {
DecimalType itemState = (DecimalType) item.getStateAs(DecimalType.class);
if(itemState!=null) {
sum = sum.add(itemState.toBigDecimal());
}
}
}
return new DecimalType(sum);
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
return null;
}
}
}
/**
* This calculates the minimum value of all item states of decimal type.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
static class Min implements GroupFunction {
public Min() {}
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
if(items!=null && items.size()>0) {
BigDecimal min = null;
for(Item item : items) {
DecimalType itemState = (DecimalType) item.getStateAs(DecimalType.class);
if(itemState!=null) {
if(min==null || min.compareTo(itemState.toBigDecimal()) > 0) {
min = itemState.toBigDecimal();
}
}
}
if(min!=null) {
return new DecimalType(min);
}
}
return UnDefType.UNDEF;
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
return null;
}
}
}
/**
* This calculates the maximum value of all item states of decimal type.
*
* @author Kai Kreuzer
* @since 0.7.0
*
*/
static class Max implements GroupFunction {
public Max() {}
/**
* @{inheritDoc
*/
public State calculate(List<Item> items) {
if(items!=null && items.size()>0) {
BigDecimal max = null;
for(Item item : items) {
DecimalType itemState = (DecimalType) item.getStateAs(DecimalType.class);
if(itemState!=null) {
if(max==null || max.compareTo(itemState.toBigDecimal()) < 0) {
max = itemState.toBigDecimal();
}
}
}
if(max!=null) {
return new DecimalType(max);
}
}
return UnDefType.UNDEF;
}
/**
* @{inheritDoc
*/
public State getStateAs(List<Item> items, Class<? extends State> stateClass) {
State state = calculate(items);
if(stateClass.isInstance(state)) {
return state;
} else {
return null;
}
}
}
}
@@ -0,0 +1,110 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import org.openhab.core.types.Command;
import org.openhab.core.types.PrimitiveType;
import org.openhab.core.types.State;
public class DateTimeType implements PrimitiveType, State, Command {
public static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
public static final String DATE_PATTERN_WITH_TZ = "yyyy-MM-dd'T'HH:mm:ssz";
protected Calendar calendar;
public DateTimeType() {
this(Calendar.getInstance());
}
public DateTimeType(Calendar calendar) {
this.calendar = calendar;
}
public DateTimeType(String calendarValue) {
Date date = null;
try {
try {
date = new SimpleDateFormat(DATE_PATTERN_WITH_TZ).parse(calendarValue);
}
catch (ParseException fpe2) {
date = new SimpleDateFormat(DATE_PATTERN).parse(calendarValue);
}
}
catch (ParseException fpe) {
throw new IllegalArgumentException(calendarValue + " is not in a valid format.", fpe);
}
if (date != null) {
calendar = Calendar.getInstance();
calendar.setTime(date);
}
}
public Calendar getCalendar() {
return calendar;
}
public static DateTimeType valueOf(String value) {
return new DateTimeType(value);
}
public String format(String pattern) {
try {
return String.format(pattern, calendar);
} catch (NullPointerException npe) {
return new SimpleDateFormat(DATE_PATTERN).format(calendar.getTime());
}
}
public String format(Locale locale, String pattern) {
return String.format(locale, pattern, calendar);
}
@Override
public String toString() {
return new SimpleDateFormat(DATE_PATTERN).format(calendar.getTime());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((calendar == null) ? 0 : calendar.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DateTimeType other = (DateTimeType) obj;
if (calendar == null) {
if (other.calendar != null)
return false;
} else if (!calendar.equals(other.calendar))
return false;
return true;
}
}
@@ -0,0 +1,120 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import java.math.BigDecimal;
import org.openhab.core.types.Command;
import org.openhab.core.types.PrimitiveType;
import org.openhab.core.types.State;
/**
* The decimal type uses a BigDecimal internally and thus can be used for
* integers, longs and floating point numbers alike.
*
* @author Kai Kreuzer
*
*/
public class DecimalType extends Number implements PrimitiveType, State, Command, Comparable<DecimalType> {
private static final long serialVersionUID = 4226845847123464690L;
final static public DecimalType ZERO = new DecimalType(0);
protected BigDecimal value;
public DecimalType() {
this.value = BigDecimal.ZERO;
}
public DecimalType(BigDecimal value) {
this.value = value;
}
public DecimalType(long value) {
this.value = new BigDecimal(value);
}
public DecimalType(double value) {
this.value = new BigDecimal(value);
}
public DecimalType(String value) {
this.value = new BigDecimal(value);
}
public String toString() {
return value.toPlainString();
}
public static DecimalType valueOf(String value) {
return new DecimalType(value);
}
public String format(String pattern) {
if (pattern.contains("%d")) {
return String.format(pattern, value.toBigInteger());
} else {
return String.format(pattern, value);
}
}
public BigDecimal toBigDecimal() {
return value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof DecimalType))
return false;
DecimalType other = (DecimalType) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (value.compareTo(other.value) != 0)
return false;
return true;
}
public int compareTo(DecimalType o) {
return value.compareTo(o.toBigDecimal());
}
@Override
public double doubleValue() {
return value.doubleValue();
}
@Override
public float floatValue() {
return value.floatValue();
}
@Override
public int intValue() {
return value.intValue();
}
@Override
public long longValue() {
return value.longValue();
}
}
@@ -0,0 +1,172 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import java.awt.Color;
import java.math.BigDecimal;
import java.util.SortedMap;
import java.util.TreeMap;
import org.openhab.core.types.Command;
import org.openhab.core.types.ComplexType;
import org.openhab.core.types.PrimitiveType;
import org.openhab.core.types.State;
/**
* The HSBType is a complex type with constituents for hue, saturation and
* brightness and can be used for color items.
*
* @author Kai Kreuzer
* @since 1.2.0
*
*/
public class HSBType extends PercentType implements ComplexType, State, Command {
private static final long serialVersionUID = 322902950356613226L;
// constants for the constituents
static final public String KEY_HUE = "h";
static final public String KEY_SATURATION = "s";
static final public String KEY_BRIGHTNESS = "b";
// constants for colors
static final public HSBType BLACK = new HSBType(Color.BLACK);
static final public HSBType WHITE = new HSBType(Color.WHITE);
static final public HSBType RED = new HSBType(Color.RED);
static final public HSBType GREEN = new HSBType(Color.GREEN);
static final public HSBType BLUE = new HSBType(Color.BLUE);
protected BigDecimal hue;
protected BigDecimal saturation;
// the inherited field "value" of the parent DecimalType corresponds to the
// "brightness"
public HSBType(Color color) {
if (color != null) {
float[] hsbValues = Color.RGBtoHSB(color.getRed(),
color.getGreen(), color.getBlue(), null);
this.hue = BigDecimal.valueOf(hsbValues[0] * 360);
this.saturation = BigDecimal.valueOf(hsbValues[1] * 100);
this.value = BigDecimal.valueOf(hsbValues[2] * 100);
} else {
throw new IllegalArgumentException(
"Constructor argument must not be null");
}
}
public HSBType(DecimalType h, PercentType s, PercentType b) {
this.hue = h.toBigDecimal();
this.saturation = s.toBigDecimal();
this.value = b.toBigDecimal();
}
public HSBType(String value) {
if (value != null) {
String[] constituents = value.split(",");
if (constituents.length == 3) {
this.hue = new BigDecimal(constituents[0]);
this.saturation = new BigDecimal(constituents[1]);
this.value = new BigDecimal(constituents[2]);
} else {
throw new IllegalArgumentException(value
+ " is not a valid HSBType syntax");
}
} else {
throw new IllegalArgumentException(
"Constructor argument must not be null");
}
}
public static HSBType valueOf(String value) {
return new HSBType(value);
}
@Override
public SortedMap<String, PrimitiveType> getConstituents() {
TreeMap<String, PrimitiveType> map = new TreeMap<String, PrimitiveType>();
map.put(KEY_HUE, getHue());
map.put(KEY_SATURATION, getSaturation());
map.put(KEY_BRIGHTNESS, getBrightness());
return map;
}
public DecimalType getHue() {
return new DecimalType(hue);
}
public PercentType getSaturation() {
return new PercentType(saturation);
}
public PercentType getBrightness() {
return new PercentType(value);
}
public PercentType getRed() {
return byteToPercentType(toColor().getRed());
}
public PercentType getGreen() {
return byteToPercentType(toColor().getGreen());
}
public PercentType getBlue() {
return byteToPercentType(toColor().getBlue());
}
private PercentType byteToPercentType(int byteValue) {
BigDecimal percentValue = new BigDecimal(byteValue).multiply(
BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(255), 2,
BigDecimal.ROUND_HALF_UP);
return new PercentType(percentValue);
}
public Color toColor() {
return Color.getHSBColor(hue.floatValue() / 360,
saturation.floatValue() / 100, value.floatValue() / 100);
}
public String toString() {
return getHue() + "," + getSaturation() + "," + getBrightness();
}
@Override
public int hashCode() {
int tmp = 10000 * (getHue() == null ? 0 : getHue().hashCode());
tmp += 100 * (getSaturation() == null ? 0 : getSaturation().hashCode());
tmp += (getBrightness() == null ? 0 : getBrightness().hashCode());
return tmp;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof HSBType))
return false;
HSBType other = (HSBType) obj;
if ((getHue() != null && other.getHue() == null)
|| (getHue() == null && other.getHue() != null)
|| (getSaturation() != null && other.getSaturation() == null)
|| (getSaturation() == null && other.getSaturation() != null)
|| (getBrightness() != null && other.getBrightness() == null)
|| (getBrightness() == null && other.getBrightness() != null)) {
return false;
}
if (!getHue().equals(other.getHue())
|| !getSaturation().equals(other.getSaturation())
|| !getBrightness().equals(other.getBrightness())) {
return false;
}
return true;
}
}
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import org.openhab.core.types.Command;
import org.openhab.core.types.PrimitiveType;
public enum IncreaseDecreaseType implements PrimitiveType, Command {
INCREASE, DECREASE;
public String format(String pattern) {
return String.format(pattern, this.toString());
}
}
@@ -0,0 +1,22 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.PrimitiveType;
public enum OnOffType implements PrimitiveType, State, Command {
ON, OFF;
public String format(String pattern) {
return String.format(pattern, this.toString());
}
}
@@ -0,0 +1,22 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.PrimitiveType;
public enum OpenClosedType implements PrimitiveType, State, Command {
OPEN, CLOSED;
public String format(String pattern) {
return String.format(pattern, this.toString());
}
}
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import java.math.BigDecimal;
/**
* The PercentType extends the {@link DecimalType} by putting constraints for its value on top (0-100).
*
* @author Kai Kreuzer
* @since 0.1.0
*
*/
public class PercentType extends DecimalType {
private static final long serialVersionUID = -9066279845951780879L;
final static public PercentType ZERO = new PercentType(0);
final static public PercentType HUNDRED = new PercentType(100);
public PercentType() {
super();
}
public PercentType(int value) {
super(value);
validateValue(this.value);
}
public PercentType(String value) {
super(value);
validateValue(this.value);
}
public PercentType(BigDecimal value) {
super(value);
validateValue(this.value);
}
private void validateValue(BigDecimal value) {
if(BigDecimal.ZERO.compareTo(value) > 0 || new BigDecimal(100).compareTo(value) < 0) {
throw new IllegalArgumentException("Value must be between 0 and 100");
}
}
public static PercentType valueOf(String value) {
return new PercentType(value);
}
}
@@ -0,0 +1,167 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import java.math.BigDecimal;
import java.util.Formatter;
import java.util.SortedMap;
import java.util.TreeMap;
import org.openhab.core.types.Command;
import org.openhab.core.types.ComplexType;
import org.openhab.core.types.PrimitiveType;
import org.openhab.core.types.State;
/**
* This type can be used for items that are dealing with GPS functionality.
*
* @author Gaël L'hopital
* @since 1.7.0
*/
public class PointType implements ComplexType, Command, State {
public static final double EARTH_GRAVITATIONAL_CONSTANT = 3.986004418e14;
public static final double WGS84_a = 6378137; // The equatorial radius of
// WGS84 ellipsoid (6378137
// m).
private BigDecimal latitude; // in decimal degrees
private BigDecimal longitude; // in decimal degrees
private BigDecimal altitude = BigDecimal.ZERO; // in decimal meters
// constants for the constituents
static final public String KEY_LATITUDE = "lat";
static final public String KEY_LONGITUDE = "long";
static final public String KEY_ALTITUDE = "alt";
private static final BigDecimal circle = new BigDecimal(360);
private static final BigDecimal flat = new BigDecimal(180);
private static final BigDecimal right = new BigDecimal(90);
public static final PointType EMPTY = new PointType(new DecimalType(0),
new DecimalType(0));
public PointType(DecimalType latitude, DecimalType longitude) {
canonicalize(latitude, longitude);
}
public PointType(DecimalType latitude, DecimalType longitude,
DecimalType altitude) {
this(latitude, longitude);
setAltitude(altitude);
}
public PointType(StringType latitude, StringType longitude) {
this(new DecimalType(latitude.toString()), new DecimalType(
longitude.toString()));
}
public PointType(StringType latitude, StringType longitude,
StringType altitude) {
this(new DecimalType(latitude.toString()), new DecimalType(
longitude.toString()), new DecimalType(altitude.toString()));
}
public PointType(String value) {
if (!value.isEmpty()) {
String[] elements = value.split(",");
if (elements.length >= 2) {
canonicalize(new DecimalType(elements[0]), new DecimalType(
elements[1]));
if (elements.length == 3) {
setAltitude(new DecimalType(elements[2]));
}
}
}
}
public DecimalType getLatitude() {
return new DecimalType(latitude);
}
public DecimalType getLongitude() {
return new DecimalType(longitude);
}
public DecimalType getAltitude() {
return new DecimalType(altitude);
}
public void setAltitude(DecimalType altitude) {
this.altitude = altitude.toBigDecimal();
}
public DecimalType getGravity() {
double latRad = Math.toRadians(latitude.doubleValue());
double deltaG = -2000.0 * (altitude.doubleValue() / 1000)
* EARTH_GRAVITATIONAL_CONSTANT / (Math.pow(WGS84_a, 3.0));
double sin2lat = Math.sin(latRad) * Math.sin(latRad);
double sin22lat = Math.sin(2.0 * latRad) * Math.sin(2.0 * latRad);
double result = (9.780327 * (1.0 + 5.3024e-3 * sin2lat - 5.8e-6 * sin22lat) + deltaG);
return new DecimalType(result);
}
/**
* <p>
* Formats the value of this type according to a pattern (@see
* {@link Formatter}). One single value of this type can be referenced by
* the pattern using an index. The item order is defined by the natural
* (alphabetical) order of their keys.
* </p>
*
* @param pattern
* the pattern to use containing indexes to reference the single
* elements of this type.
*/
@Override
public String format(String pattern) {
return String.format(pattern, getConstituents().values().toArray());
}
public PointType valueOf(String value) {
return new PointType(value);
}
@Override
public String toString() {
return String.format("%1$.2f°N, %2$.2f°W, %3$.2f m", latitude, longitude, altitude);
}
@Override
public SortedMap<String, PrimitiveType> getConstituents() {
SortedMap<String, PrimitiveType> result = new TreeMap<String, PrimitiveType>();
result.put(KEY_LATITUDE, getLatitude());
result.put(KEY_LONGITUDE, getLongitude());
result.put(KEY_ALTITUDE, getAltitude());
return result;
}
/**
* Canonicalize the current latitude and longitude values such that:
*
* <pre>
* -90 &lt;= latitude &lt;= +90 - 180 &lt; longitude &lt;= +180
* </pre>
*/
private void canonicalize(DecimalType aLat, DecimalType aLon) {
latitude = flat.add(aLat.toBigDecimal()).remainder(circle);
longitude = aLon.toBigDecimal();
if (latitude.compareTo(BigDecimal.ZERO) == -1)
latitude.add(circle);
latitude = latitude.subtract(flat);
if (latitude.compareTo(right) == 1) {
latitude = flat.subtract(latitude);
longitude = longitude.add(flat);
} else if (latitude.compareTo(right.negate()) == -1) {
latitude = flat.negate().subtract(latitude);
longitude = longitude.add(flat);
}
longitude = flat.add(longitude).remainder(circle);
if (longitude.compareTo(BigDecimal.ZERO) <= 0)
longitude = longitude.add(circle);
longitude = longitude.subtract(flat);
}
}
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import org.openhab.core.types.Command;
import org.openhab.core.types.PrimitiveType;
public enum StopMoveType implements PrimitiveType, Command {
STOP, MOVE;
public String format(String pattern) {
return String.format(pattern, this.toString());
}
}
@@ -0,0 +1,61 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.PrimitiveType;
public class StringType implements PrimitiveType, State, Command {
public final static StringType EMPTY = new StringType("");
private final String value;
public StringType(String value) {
this.value = value;
}
public String toString() {
return value;
}
public static StringType valueOf(String value) {
return new StringType(value);
}
public String format(String pattern) {
return String.format(pattern, value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if(obj instanceof String) {
return obj.equals(value);
}
if (getClass() != obj.getClass())
return false;
StringType other = (StringType) obj;
if (!value.equals(other.value)) {
return false;
}
return true;
}
}
@@ -0,0 +1,22 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.library.types;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.PrimitiveType;
public enum UpDownType implements PrimitiveType, State, Command {
UP, DOWN;
public String format(String pattern) {
return String.format(pattern, this.toString());
}
}
@@ -0,0 +1,154 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence;
import java.util.Date;
import org.openhab.core.types.State;
/**
* This class is used to define a filter for queries to a {@link PersistenceService}.
*
* <p>It is designed as a Java bean, for which the different properties are constraints
* on the query result. These properties include the item name, begin and end date and
* the item state. A compare operator can be defined to compare not only state equality,
* but also its decimal value (<,>).<p>
* <p>Additionally, the filter criteria supports ordering and paging of the result, so the
* caller can ask to only return chunks of the result of a certain size (=pageSize) from a
* starting index (pageNumber*pageSize).</p>
* <p>All setter methods return the filter criteria instance, so that the methods can be
* easily chained in order to define a filter.
*
* @author Kai Kreuzer
* @since 1.0.0
*/
public class FilterCriteria {
/** Enumeration with all possible compare options */
public enum Operator {
EQ("="),
NEQ("!="),
GT(">"),
LT("<"),
GTE(">="),
LTE("<=");
private final String symbol;
Operator(String symbol) {
this.symbol = symbol;
}
String getSymbol() {
return symbol;
}
}
/** Enumeration with all ordering options */
public enum Ordering {
ASCENDING, DESCENDING
}
/** filter result to only contain entries for the given item */
private String itemName;
/** filter result to only contain entries that are newer than the given date */
private Date beginDate;
/** filter result to only contain entries that are older than the given date */
private Date endDate;
/** return the result list from starting index pageNumber*pageSize only */
private int pageNumber = 0;
/** return at most this many results */
private int pageSize = Integer.MAX_VALUE;
/** use this operator to compare the item state */
private Operator operator = Operator.EQ;
/** how to sort the result list by date */
private Ordering ordering = Ordering.DESCENDING;
/** filter result to only contain entries that evaluate to true with the given operator and state */
private State state;
public String getItemName() {
return itemName;
}
public Date getBeginDate() {
return beginDate;
}
public Date getEndDate() {
return endDate;
}
public int getPageNumber() {
return pageNumber;
}
public int getPageSize() {
return pageSize;
}
public Operator getOperator() {
return operator;
}
public Ordering getOrdering() {
return ordering;
}
public State getState() {
return state;
}
public FilterCriteria setItemName(String itemName) {
this.itemName = itemName;
return this;
}
public FilterCriteria setBeginDate(Date beginDate) {
this.beginDate = beginDate;
return this;
}
public FilterCriteria setEndDate(Date endDate) {
this.endDate = endDate;
return this;
}
public FilterCriteria setPageNumber(int pageNumber) {
this.pageNumber = pageNumber;
return this;
}
public FilterCriteria setPageSize(int pageSize) {
this.pageSize = pageSize;
return this;
}
public FilterCriteria setOperator(Operator operator) {
this.operator = operator;
return this;
}
public FilterCriteria setOrdering(Ordering ordering) {
this.ordering = ordering;
return this;
}
public FilterCriteria setState(State state) {
this.state = state;
return this;
}
}
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence;
import java.util.Date;
import org.openhab.core.types.State;
/**
* This interface is used by persistence services to represent an item
* with a certain state at a given point in time.
*
* <p>Note that this interface does not extend {@link Item} as the persistence
* services could not provide an implementation that correctly implement
* getAcceptedXTypes() and getGroupNames().</p>
*
* @author Kai Kreuzer
* @since 1.0.0
*/
public interface HistoricItem {
/**
* returns the timestamp of the persisted item
*
* @return the timestamp of the item
*/
Date getTimestamp();
/**
* returns the current state of the item
*
* @return the current state
*/
public State getState();
/**
* returns the name of the item
*
* @return the name of the item
*/
public String getName();
}
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence;
import org.openhab.core.items.Item;
/**
* A persistence service which can be used to store data from openHAB.
* This must not necessarily be a local database, a persistence service
* can also be cloud-based or a simply data-export facility (e.g.
* for sending data to an IoT (Internet of Things) service.
*
* @author Kai Kreuzer
* @since 1.0.0
*/
public interface PersistenceService {
/**
* Returns the name of this {@link PersistenceService}.
* This name is used to uniquely identify the {@link PersistenceService}.
*
* @return the name to uniquely identify the {@link PersistenceService}.
*/
String getName();
/**
* Stores the current value of the given item.
* <p>Implementors should keep in mind that all registered
* {@link PersistenceService}s are called synchronously. Hence long running
* operations should be processed asynchronously. E.g. <code>store</code>
* adds things to a queue which is processed by some asynchronous workers
* (Quartz Job, Thread, etc.).</p>
*
* @param item the item which state should be persisted.
*/
void store(Item item);
/**
* <p>Stores the current value of the given item under a specified alias.</p>
* <p>Implementors should keep in mind that all registered
* {@link PersistenceService}s are called synchronously. Hence long running
* operations should be processed asynchronously. E.g. <code>store</code>
* adds things to a queue which is processed by some asynchronous workers
* (Quartz Job, Thread, etc.).</p>
*
* @param item the item which state should be persisted.
* @param alias the alias under which the item should be persisted.
*/
void store(Item item, String alias);
}
@@ -0,0 +1,28 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence;
/**
* A queryable persistence service which can be used to store and retrieve
* data from openHAB. This is most likely some kind of database system.
*
* @author Kai Kreuzer
* @since 1.0.0
*/
public interface QueryablePersistenceService extends PersistenceService {
/**
* Queries the {@link PersistenceService} for data with a given filter criteria
*
* @param filter the filter to apply to the query
* @return a time series of items
*/
Iterable<HistoricItem> query(FilterCriteria filter);
}
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence.internal;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.persistence.PersistenceService;
import org.openhab.core.compat1x.internal.ItemMapper;
/**
* This class serves as a mapping from the "old" org.openhab namespace to the new org.eclipse.smarthome
* namespace for the persistence service. It wraps an instance with the old interface
* into a class with the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class PersistenceServiceDelegate implements PersistenceService {
protected org.openhab.core.persistence.PersistenceService service;
public PersistenceServiceDelegate(org.openhab.core.persistence.PersistenceService service) {
this.service = service;
}
@Override
public String getName() {
return service.getName();
}
@Override
public void store(Item item) {
org.openhab.core.items.Item ohItem = ItemMapper.mapToOpenHABItem(item);
if(ohItem!=null) {
service.store(ohItem);
}
}
@Override
public void store(Item item, String alias) {
org.openhab.core.items.Item ohItem = ItemMapper.mapToOpenHABItem(item);
if(ohItem!=null) {
service.store(ohItem, alias);
}
}
}
@@ -0,0 +1,85 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence.internal;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import org.openhab.core.persistence.PersistenceService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
/**
* This class listens for services that implement the old persistence service interface and registers
* an according service for each under the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class PersistenceServiceFactory {
private Map<String, ServiceRegistration<org.eclipse.smarthome.core.persistence.PersistenceService>> delegates = new HashMap<>();
private BundleContext context;
private Set<PersistenceService> persistenceServices = new HashSet<>();
public void activate(BundleContext context) {
this.context = context;
for(PersistenceService service : persistenceServices) {
registerDelegateService(service);
}
}
public void deactivate() {
for(ServiceRegistration<org.eclipse.smarthome.core.persistence.PersistenceService> serviceReg : delegates.values()) {
serviceReg.unregister();
}
delegates.clear();
this.context = null;
}
public void addPersistenceService(PersistenceService service) {
if(context!=null) {
registerDelegateService(service);
} else {
persistenceServices.add(service);
}
}
public void removePersistenceService(PersistenceService service) {
if(context!=null) {
unregisterDelegateService(service);
}
}
private void registerDelegateService(PersistenceService persistenceService) {
if(!delegates.containsKey(persistenceService.getName())) {
org.eclipse.smarthome.core.persistence.PersistenceService service =
(persistenceService instanceof org.openhab.core.persistence.QueryablePersistenceService) ?
new QueryablePersistenceServiceDelegate(persistenceService)
: new PersistenceServiceDelegate(persistenceService);
Dictionary<String, Object> props = new Hashtable<String, Object>();
ServiceRegistration<org.eclipse.smarthome.core.persistence.PersistenceService> serviceReg =
context.registerService(org.eclipse.smarthome.core.persistence.PersistenceService.class, service, props);
delegates.put(persistenceService.getName(), serviceReg);
}
}
private void unregisterDelegateService(PersistenceService service) {
if(delegates.containsKey(service.getName())) {
ServiceRegistration<org.eclipse.smarthome.core.persistence.PersistenceService> serviceReg =
delegates.get(service.getName());
delegates.remove(service.getName());
serviceReg.unregister();
}
}
}
@@ -0,0 +1,87 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.persistence.internal;
import java.util.ArrayList;
import java.util.Date;
import org.eclipse.smarthome.core.persistence.FilterCriteria;
import org.eclipse.smarthome.core.persistence.HistoricItem;
import org.eclipse.smarthome.core.persistence.QueryablePersistenceService;
import org.eclipse.smarthome.core.types.State;
import org.openhab.core.compat1x.internal.TypeMapper;
import org.openhab.core.persistence.FilterCriteria.Operator;
import org.openhab.core.persistence.FilterCriteria.Ordering;
/**
* This class serves as a mapping from the "old" org.openhab namespace to the new org.eclipse.smarthome
* namespace for the queryable persistence service. It wraps an instance with the old interface
* into a class with the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class QueryablePersistenceServiceDelegate extends PersistenceServiceDelegate implements QueryablePersistenceService {
public QueryablePersistenceServiceDelegate(
org.openhab.core.persistence.PersistenceService persistenceService) {
super(persistenceService);
}
@Override
public Iterable<HistoricItem> query(FilterCriteria filter) {
org.openhab.core.persistence.FilterCriteria mappedFilter = new org.openhab.core.persistence.FilterCriteria()
.setBeginDate(filter.getBeginDate())
.setEndDate(filter.getEndDate())
.setItemName(filter.getItemName())
.setOperator(mapOperator(filter.getOperator()))
.setOrdering(mapOrdering(filter.getOrdering()))
.setPageNumber(filter.getPageNumber())
.setPageSize(filter.getPageSize())
.setState(mapState(filter.getState()));
org.openhab.core.persistence.QueryablePersistenceService pService = (org.openhab.core.persistence.QueryablePersistenceService) service;
Iterable<org.openhab.core.persistence.HistoricItem> historicItems = pService.query(mappedFilter);
ArrayList<HistoricItem> result = new ArrayList<>();
for(final org.openhab.core.persistence.HistoricItem item : historicItems) {
result.add(new HistoricItem() {
@Override
public Date getTimestamp() {
return item.getTimestamp();
}
@Override
public State getState() {
return (State) TypeMapper.mapToESHType(item.getState());
}
@Override
public String getName() {
return item.getName();
}
});
}
return result;
}
private org.openhab.core.types.State mapState(State state) {
return (org.openhab.core.types.State) TypeMapper.mapToOpenHABType(state);
}
private Ordering mapOrdering(FilterCriteria.Ordering ordering) {
if(ordering==null) return null;
return org.openhab.core.persistence.FilterCriteria.Ordering.valueOf(ordering.toString());
}
private Operator mapOperator(FilterCriteria.Operator operator) {
if(operator==null) return null;
return org.openhab.core.persistence.FilterCriteria.Operator.valueOf(operator.toString());
}
}
@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.scriptengine.action;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface ActionDoc {
String text();
String returns() default "";
}
@@ -0,0 +1,33 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.scriptengine.action;
/**
* This interface must be implemented by services that want to contribute script actions.
*
* @author Kai Kreuzer
* @since 1.3.0
*/
public interface ActionService {
/**
* returns the FQCN of the action class.
*
* @return the FQCN of the action class
*/
String getActionClassName();
/**
* Returns the action class itself
*
* @return the action class
*/
Class<?> getActionClass();
}
@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.scriptengine.action;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamDoc {
String name();
String text() default "";
}
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2015-2015 Kai Kreuzer and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.core.scriptengine.action.internal;
import org.eclipse.smarthome.model.script.engine.action.ActionService;
/**
* This class serves as a mapping from the "old" org.openhab namespace to the new org.eclipse.smarthome
* namespace for the action service. It wraps an instance with the old interface
* into a class with the new interface.
*
* @author Kai Kreuzer - Initial contribution and API
*/
public class ActionServiceDelegate implements ActionService {
private org.openhab.core.scriptengine.action.ActionService service;
public ActionServiceDelegate(org.openhab.core.scriptengine.action.ActionService service) {
this.service = service;
}
@Override
public String getActionClassName() {
return service.getActionClassName();
}
@Override
public Class<?> getActionClass() {
return service.getActionClass();
}
}

Some files were not shown because too many files have changed in this diff Show More