Initial codebase after move from https://github.com/mortommy/openhab-mycroft
Signed-off-by: Tommaso Morello <tommaso.morello@gmail.com> (github: mortommy)pull/4/head
parent
41d5bec2d5
commit
574c3244eb
|
@ -0,0 +1,156 @@
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
### Discuss your design on the mailing list
|
||||||
|
|
||||||
|
We recommend discussing your plans [in the discussion forum](https://community.openhab.org/)
|
||||||
|
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/openhab-mycroft/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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Merge approval
|
||||||
|
|
||||||
|
openHAB-Mycroft maintainers use LGTM (Looks Good To Me) in comments on the code review
|
||||||
|
to indicate acceptance.
|
||||||
|
|
||||||
|
### 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.)
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
|
||||||
|
## Community Guidelines
|
||||||
|
|
||||||
|
We want to keep the openHAB-Mycroft 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.
|
|
@ -0,0 +1,80 @@
|
||||||
|
# openHAB skill for Mycroft
|
||||||
|
|
||||||
|
This skill adds [openHAB](http://www.openhab.org/) support to [Mycroft](https://mycroft.ai).
|
||||||
|
The skill takes advantage of the openHAB REST API, so it works both with the v1.x and v2.x of openHAB.
|
||||||
|
|
||||||
|
Some sample voice commands are:
|
||||||
|
|
||||||
|
- *"Hey Mycroft, turn on Diningroom Light"*
|
||||||
|
- *"Hey Mycroft, switch off Kitchen Light"*
|
||||||
|
- *"Hey Mycroft, put on Good Night"*
|
||||||
|
- *"Hey Mycroft, set Diningroom to 50 percent"*
|
||||||
|
- *"Hey Mycroft, dim Kitchen"*
|
||||||
|
- *"Hey Mycroft, brighten Kitchen"*
|
||||||
|
- *"Hey Mycroft, dim Kitchen by 20 percent"*
|
||||||
|
- *"Hey Mycroft, what's Bedroom temperature?"*
|
||||||
|
- *"Hey Mycroft, what's Bedroom humidity?"*
|
||||||
|
- *"Hey Mycroft, adjust Main Thermostat to 21 degrees"*
|
||||||
|
- *"Hey Mycroft, regulate Main Thermostat to 20 degrees"*
|
||||||
|
- *"Hey Mycroft, decrease Main Thermostat by 2 degrees"*
|
||||||
|
- *"Hey Mycroft, increase Main Thermostat by 1 degrees"*
|
||||||
|
- *"Hey Mycroft, what is Main Thermostat regulated to?"*
|
||||||
|
- *"Hey Mycroft, what is Main Thermostat tuned to?"*
|
||||||
|
|
||||||
|
## openHAB Item Configuration
|
||||||
|
|
||||||
|
In order to make openHAB Items accessible to Mycroft, they need to be [tagged](http://docs.openhab.org/addons/io/homekit/readme.html).
|
||||||
|
Device names recognized by Mycroft are matched against openHAB Item Labels.
|
||||||
|
|
||||||
|
The above examples would all work with the following set of openHAB Item definitons:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Color DiningroomLight "Diningroom Light" <light> (gKitchen) [ "Lighting" ] {channel="hue:0200:1:bloom1:color"}
|
||||||
|
Color KitchenLight "Kitchen Light" <light> (gKitchen) [ "Lighting" ] {channel="hue:0200:1:bloom1:color"}
|
||||||
|
Switch GoodNight "Good Night" [ "Switchable" ]
|
||||||
|
|
||||||
|
Number MqttID1Temperature "Bedroom Temperature" <temperature> [ "CurrentTemperature" ] {mqtt="<[mosquitto:mysensors/SI/1/1/1/0/0:state:default]"}
|
||||||
|
Number MqttID1Humidity "Bedroom Humidity" [ "CurrentHumidity" ] {mqtt="<[mosquitto:mysensors/SI/1/0/1/0/1:state:default]"}
|
||||||
|
|
||||||
|
Group gThermostat "Main Thermostat" [ "gMainThermostat" ]
|
||||||
|
Number MainThermostatCurrentTemp "Main Thermostat Current Temperature" (gMainThermostat) [ "CurrentTemperature" ]
|
||||||
|
Number MainThermostatTargetTemperature "Main Thermostat Target Temperature" (gMainThermostat) [ "TargetTemperature" ]
|
||||||
|
String MainThermostatHeatingCoolingMode "Main Thermostat Heating/Cooling Mode" (gMainThermostat) [ "homekit:HeatingCoolingMode" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
If items are modified in openHAB, a refresh in Mycroft is needed by the command:
|
||||||
|
|
||||||
|
- *"Hey Mycroft, refresh openhab items"*
|
||||||
|
|
||||||
|
## Versions Change Log
|
||||||
|
* 1.0 added support to item tagged as Thermostat, CurrentTemperature, CurrentHumidity
|
||||||
|
* 0.9 added dimming command to item tagged as Lighting
|
||||||
|
* 0.8 supports only Lighting and Switchable tags, commands ON and OFF
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Clone this repository into your `~/.mycroft/skills` directory.
|
||||||
|
Then install the dependencies inside your mycroft virtual environment:
|
||||||
|
|
||||||
|
If on picroft just skip the workon part and the directory will be `/opt/mycroft/skills`
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd ~/.mycroft/skills
|
||||||
|
git clone https://github.com/mortommy/mycroft-skill-openhab skill-openhab
|
||||||
|
workon mycroft
|
||||||
|
cd skill-openhab
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Add the block below to your `mycoft.conf` file:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"openHABSkill": {
|
||||||
|
"host": "openHAB server ip",
|
||||||
|
"port": "openHAB server port"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart mycroft for the changes to take effect.
|
|
@ -0,0 +1,321 @@
|
||||||
|
# Copyright (c) 2010-2017 by the respective copyright holders.
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from os.path import dirname
|
||||||
|
|
||||||
|
from adapt.intent import IntentBuilder
|
||||||
|
from mycroft.skills.core import MycroftSkill
|
||||||
|
from mycroft.util.log import getLogger
|
||||||
|
from fuzzywuzzy import fuzz
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
# v 0.1 - just switch on and switch off a fix light
|
||||||
|
# v 0.2 - code review
|
||||||
|
# v 0.3 - first working version on fixed light item
|
||||||
|
# v 0.4 - getTaggedItems method in order to get all the tagged items from openHAB
|
||||||
|
# v 0.5 - refresh tagged item intent
|
||||||
|
# v 0.6 - add findItemName method and import fuzzywuzzy
|
||||||
|
# v 0.7 - add intent for switchable items
|
||||||
|
# v 0.8 - merged lighting and switchable intent in onoff intent
|
||||||
|
# v 0.9 - added support to dimmable items
|
||||||
|
# v 1.0 - added Thermostat tag support
|
||||||
|
|
||||||
|
__author__ = 'mortommy'
|
||||||
|
|
||||||
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
|
class openHABSkill(MycroftSkill):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(openHABSkill, self).__init__(name="openHABSkill")
|
||||||
|
|
||||||
|
self.url = "http://%s:%s/rest" % (self.config.get('host'), self.config.get('port'))
|
||||||
|
|
||||||
|
self.command_headers = {"Content-type": "text/plain"}
|
||||||
|
|
||||||
|
self.polling_headers = {"Accept": "application/json"}
|
||||||
|
|
||||||
|
self.lightingItemsDic = dict()
|
||||||
|
self.switchableItemsDic = dict()
|
||||||
|
self.currentTempItemsDic = dict()
|
||||||
|
self.currentHumItemsDic = dict()
|
||||||
|
#self.currentThermostatItemsDic = dict()
|
||||||
|
self.targetTemperatureItemsDic = dict()
|
||||||
|
#self.homekitHeatingCoolingModeDic = dict()
|
||||||
|
|
||||||
|
self.getTaggedItems()
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
|
||||||
|
refresh_tagged_items_intent = IntentBuilder("RefreshTaggedItemsIntent").require("RefreshTaggedItemsKeyword").build()
|
||||||
|
self.register_intent(refresh_tagged_items_intent, self.handle_refresh_tagged_items_intent)
|
||||||
|
|
||||||
|
onoff_status_intent = IntentBuilder("OnOff_StatusIntent").require("OnOffStatusKeyword").require("Command").require("Item").build()
|
||||||
|
self.register_intent(onoff_status_intent, self.handle_onoff_status_intent)
|
||||||
|
|
||||||
|
dimmer_status_intent = IntentBuilder("Dimmer_StatusIntent").require("DimmerStatusKeyword").require("Item").optionally("BrigthPercentage").build()
|
||||||
|
self.register_intent(dimmer_status_intent, self.handle_dimmer_status_intent)
|
||||||
|
|
||||||
|
what_status_intent = IntentBuilder("What_StatusIntent").require("WhatStatusKeyword").require("Item").require("RequestType").build()
|
||||||
|
self.register_intent(what_status_intent, self.handle_what_status_intent)
|
||||||
|
|
||||||
|
setTemp_status_intent = IntentBuilder("SetTemp_StatusIntent").require("ThermostatStatusKeyword").require("Item").require("TempValue").build()
|
||||||
|
self.register_intent(setTemp_status_intent, self.handle_setTemp_status_intent)
|
||||||
|
|
||||||
|
def getTaggedItems(self):
|
||||||
|
#find all the items tagged Lighting and Switchable from openHAB
|
||||||
|
#the labeled items are stored in dictionaries
|
||||||
|
|
||||||
|
self.lightingItemsDic = {}
|
||||||
|
self.switchableItemsDic = {}
|
||||||
|
self.currentTempItemsDic = {}
|
||||||
|
self.currentHumItemsDic = {}
|
||||||
|
self.currentThermostatItemsDic = {}
|
||||||
|
self.targetTemperatureItemsDic = {}
|
||||||
|
self.homekitHeatingCoolingModeDic = {}
|
||||||
|
|
||||||
|
requestUrl = self.url+"/items?recursive=false"
|
||||||
|
|
||||||
|
try:
|
||||||
|
req = requests.get(requestUrl, headers=self.polling_headers)
|
||||||
|
if req.status_code == 200:
|
||||||
|
json_response = req.json()
|
||||||
|
for x in range(0,len(json_response)):
|
||||||
|
if ("Lighting" in json_response[x]['tags']):
|
||||||
|
self.lightingItemsDic.update({json_response[x]['name']: json_response[x]['label']})
|
||||||
|
elif ("Switchable" in json_response[x]['tags']):
|
||||||
|
self.switchableItemsDic.update({json_response[x]['name']: json_response[x]['label']})
|
||||||
|
elif ("CurrentTemperature" in json_response[x]['tags']):
|
||||||
|
self.currentTempItemsDic.update({json_response[x]['name']: json_response[x]['label']})
|
||||||
|
elif ("CurrentHumidity" in json_response[x]['tags']):
|
||||||
|
self.currentHumItemsDic.update({json_response[x]['name']: json_response[x]['label']})
|
||||||
|
elif ("Thermostat" in json_response[x]['tags']):
|
||||||
|
self.currentThermostatItemsDic.update({json_response[x]['name']: json_response[x]['label']})
|
||||||
|
elif ("TargetTemperature" in json_response[x]['tags']):
|
||||||
|
self.targetTemperatureItemsDic.update({json_response[x]['name']: ""})
|
||||||
|
elif ("homekit:HeatingCoolingMode" in json_response[x]['tags']):
|
||||||
|
self.homekitHeatingCoolingModeDic.update({json_response[x]['name']: json_response[x]['label']})
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
LOGGER.error("Some issues with the command execution!")
|
||||||
|
self.speak_dialog('GetItemsListError')
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def findItemName(self, itemDictionary, messageItem):
|
||||||
|
|
||||||
|
bestScore = 0
|
||||||
|
score = 0
|
||||||
|
bestItem = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
for itemName, itemLabel in itemDictionary.items():
|
||||||
|
score = fuzz.ratio(messageItem, itemLabel)
|
||||||
|
if score > bestScore:
|
||||||
|
bestScore = score
|
||||||
|
bestItem = itemName
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return bestItem
|
||||||
|
|
||||||
|
def handle_refresh_tagged_items_intent(self, message):
|
||||||
|
#to refresh the openHAB items labeled list we use an intent, we can ask Mycroft to make the refresh
|
||||||
|
|
||||||
|
self.getTaggedItems()
|
||||||
|
dictLenght = str(len(self.lightingItemsDic) + len(self.switchableItemsDic) + len(self.currentTempItemsDic) + len(self.currentHumItemsDic) + len(self.currentThermostatItemsDic) + len(self.targetTemperatureItemsDic) + len(self.homekitHeatingCoolingModeDic))
|
||||||
|
self.speak_dialog('RefreshTaggedItems', {'number_item': dictLenght})
|
||||||
|
|
||||||
|
def handle_onoff_status_intent(self, message):
|
||||||
|
command = message.data.get('Command')
|
||||||
|
messageItem = message.data.get('Item')
|
||||||
|
|
||||||
|
#We have to find the item to update from our dictionaries
|
||||||
|
self.lightingSwitchableItemsDic = dict()
|
||||||
|
self.lightingSwitchableItemsDic.update(self.lightingItemsDic)
|
||||||
|
self.lightingSwitchableItemsDic.update(self.switchableItemsDic)
|
||||||
|
|
||||||
|
ohItem = self.findItemName(self.lightingSwitchableItemsDic, messageItem)
|
||||||
|
|
||||||
|
if ohItem != None:
|
||||||
|
if (command != "on") and (command != "off"):
|
||||||
|
self.speak_dialog('ErrorDialog')
|
||||||
|
else:
|
||||||
|
statusCode = self.sendCommandToItem(ohItem, command.upper())
|
||||||
|
if statusCode == 200:
|
||||||
|
self.speak_dialog('StatusOnOff', {'command': command, 'item': messageItem})
|
||||||
|
elif statusCode == 404:
|
||||||
|
LOGGER.error("Some issues with the command execution!. Item not found")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
else:
|
||||||
|
LOGGER.error("Some issues with the command execution!")
|
||||||
|
self.speak_dialog('CommunicationError')
|
||||||
|
else:
|
||||||
|
LOGGER.error("Item not found!")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
|
||||||
|
def handle_dimmer_status_intent(self, message):
|
||||||
|
command = message.data.get('DimmerStatusKeyword')
|
||||||
|
messageItem = message.data.get('Item')
|
||||||
|
brightValue = message.data.get('BrigthPercentage', None)
|
||||||
|
|
||||||
|
statusCode = 0
|
||||||
|
newBrightValue = 0
|
||||||
|
|
||||||
|
ohItem = self.findItemName(self.lightingItemsDic, messageItem)
|
||||||
|
|
||||||
|
if ohItem != None:
|
||||||
|
if (command == "set"):
|
||||||
|
if ((int(brightValue) < 0) or (int(brightValue) > 100)):
|
||||||
|
self.speak_dialog('ErrorDialog')
|
||||||
|
else:
|
||||||
|
statusCode = self.sendCommandToItem(ohItem, brightValue)
|
||||||
|
else:
|
||||||
|
#find current item statusCode
|
||||||
|
state = self.getCurrentItemStatus(ohItem)
|
||||||
|
if (state != None):
|
||||||
|
#dim or brighten the value
|
||||||
|
curBrightList = state.split(',')
|
||||||
|
curBright = int(curBrightList[len(curBrightList)-1])
|
||||||
|
|
||||||
|
if(brightValue == None):
|
||||||
|
brightValue = "10"
|
||||||
|
|
||||||
|
if (command == "dim"):
|
||||||
|
newBrightValue = curBright-(int(brightValue))
|
||||||
|
else:
|
||||||
|
newBrightValue = curBright+(int(brightValue))
|
||||||
|
|
||||||
|
if (newBrightValue < 0):
|
||||||
|
newBrightValue = 0
|
||||||
|
elif (newBrightValue > 100):
|
||||||
|
newBrightValue = 100
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
#send command to item
|
||||||
|
statusCode = self.sendCommandToItem(ohItem, str(newBrightValue))
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if statusCode == 200:
|
||||||
|
self.speak_dialog('StatusDimmer', {'item': messageItem})
|
||||||
|
elif statusCode == 404:
|
||||||
|
LOGGER.error("Some issues with the command execution!. Item not found")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
else:
|
||||||
|
LOGGER.error("Some issues with the command execution!")
|
||||||
|
self.speak_dialog('CommunicationError')
|
||||||
|
|
||||||
|
else:
|
||||||
|
LOGGER.error("Item not found!")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
|
||||||
|
def handle_what_status_intent(self, message):
|
||||||
|
messageItem = message.data.get('Item')
|
||||||
|
requestType = message.data.get('RequestType')
|
||||||
|
unitOfMeasure = "degree"
|
||||||
|
infoType = "temperature"
|
||||||
|
|
||||||
|
self.currStatusItemsDic = dict()
|
||||||
|
|
||||||
|
if(requestType == "temperature"):
|
||||||
|
self.currStatusItemsDic.update(self.currentTempItemsDic)
|
||||||
|
elif(requestType == "humidity"):
|
||||||
|
unitOfMeasure = "percentage"
|
||||||
|
infoType = "humidity"
|
||||||
|
self.currStatusItemsDic.update(self.currentHumItemsDic)
|
||||||
|
else:
|
||||||
|
self.currStatusItemsDic.update(self.targetTemperatureItemsDic)
|
||||||
|
|
||||||
|
ohItem = self.findItemName(self.currStatusItemsDic, messageItem)
|
||||||
|
|
||||||
|
if ohItem != None:
|
||||||
|
state = self.getCurrentItemStatus(ohItem)
|
||||||
|
self.speak_dialog('TempHumStatus', {'item': messageItem, 'temp_hum': infoType, 'temp_hum_val': state, 'units_of_measurement': unitOfMeasure})
|
||||||
|
else:
|
||||||
|
LOGGER.error("Item not found!")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
|
||||||
|
def handle_setTemp_status_intent(self, message):
|
||||||
|
command = message.data.get('ThermostatStatusKeyword')
|
||||||
|
messageItem = message.data.get('Item')
|
||||||
|
tempVal = message.data.get('TempValue')
|
||||||
|
|
||||||
|
statusCode = 0
|
||||||
|
newTempValue = 0
|
||||||
|
|
||||||
|
ohItem = self.findItemName(self.targetTemperatureItemsDic, messageItem)
|
||||||
|
|
||||||
|
if ohItem != None:
|
||||||
|
if((command == "regulate") or (command == "adjust") or (command == "tune")):
|
||||||
|
statusCode = self.sendCommandToItem(ohItem, tempVal)
|
||||||
|
newTempValue = tempVal
|
||||||
|
else:
|
||||||
|
state = self.getCurrentItemStatus(ohItem)
|
||||||
|
if ((state != None) and (state.isdigit())):
|
||||||
|
if (command == "increase"):
|
||||||
|
newTempValue = int(state)+(int(tempVal))
|
||||||
|
else:
|
||||||
|
newTempValue = int(state)-(int(tempVal))
|
||||||
|
|
||||||
|
statusCode = self.sendCommandToItem(ohItem, str(newTempValue))
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if statusCode == 200:
|
||||||
|
self.speak_dialog('ThermostatStatus', {'item': messageItem, 'temp_val': str(newTempValue)})
|
||||||
|
elif statusCode == 404:
|
||||||
|
LOGGER.error("Some issues with the command execution!. Item not found")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
else:
|
||||||
|
LOGGER.error("Some issues with the command execution!")
|
||||||
|
self.speak_dialog('CommunicationError')
|
||||||
|
|
||||||
|
else:
|
||||||
|
LOGGER.error("Item not found!")
|
||||||
|
self.speak_dialog('ItemNotFoundError')
|
||||||
|
|
||||||
|
def sendStatusToItem(self, ohItem, command):
|
||||||
|
requestUrl = self.url+"/items/%s/state" % (ohItem)
|
||||||
|
req = requests.put(requestUrl, data=command, headers=self.command_headers)
|
||||||
|
|
||||||
|
return req.status_code
|
||||||
|
|
||||||
|
def sendCommandToItem(self, ohItem, command):
|
||||||
|
requestUrl = self.url+"/items/%s" % (ohItem)
|
||||||
|
req = requests.post(requestUrl, data=command, headers=self.command_headers)
|
||||||
|
|
||||||
|
return req.status_code
|
||||||
|
|
||||||
|
def getCurrentItemStatus(self, ohItem):
|
||||||
|
requestUrl = self.url+"/items/%s/state" % (ohItem)
|
||||||
|
state = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
req = requests.get(requestUrl, headers=self.command_headers)
|
||||||
|
|
||||||
|
if req.status_code == 200:
|
||||||
|
state = req.text
|
||||||
|
else:
|
||||||
|
LOGGER.error("Some issues with the command execution!")
|
||||||
|
self.speak_dialog('CommunicationError')
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return state
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_skill():
|
||||||
|
return openHABSkill()
|
|
@ -0,0 +1 @@
|
||||||
|
Sorry. Some problems with the command.
|
|
@ -0,0 +1,3 @@
|
||||||
|
I don't know what to do
|
||||||
|
I don't understand
|
||||||
|
I'm lost
|
|
@ -0,0 +1 @@
|
||||||
|
Sorry cannot get the items list.
|
|
@ -0,0 +1 @@
|
||||||
|
Sorry. Item not found in open hab.
|
|
@ -0,0 +1 @@
|
||||||
|
All right. I found {{number_item}} items.
|
|
@ -0,0 +1 @@
|
||||||
|
bright changed for {{item}}
|
|
@ -0,0 +1,3 @@
|
||||||
|
put {{command}} {{item}}
|
||||||
|
switch {{command}} {{item}}
|
||||||
|
turn {{command}} {{item}}
|
|
@ -0,0 +1 @@
|
||||||
|
the {{item}} {{temp_hum}} is {{temp_hum_val}} {{units_of_measurement}}
|
|
@ -0,0 +1,3 @@
|
||||||
|
regulated {{item}} to {{temp_val}} degrees
|
||||||
|
adjusted {{item}} to {{temp_val}} degrees
|
||||||
|
tuned {{item}} to {{temp_val}} degrees
|
|
@ -0,0 +1,2 @@
|
||||||
|
(set) (?P<Item>.*) (to) (?P<BrigthPercentage>\d*)(?: percent)?
|
||||||
|
(dim|brighten) (?P<Item>.*?)\s*(?: by )?(?P<BrigthPercentage>\d*)?(?: percent)?$
|
|
@ -0,0 +1 @@
|
||||||
|
(turn|switch|put) (?P<Command>on|off) (?P<Item>.*)
|
|
@ -0,0 +1,2 @@
|
||||||
|
(regulate|adjust|tune) (?P<Item>.*) (to) (?P<TempValue>\d*) (degrees)
|
||||||
|
(increase|decrease) (?P<Item>.*) (by) (?P<TempValue>\d*) (degrees)
|
|
@ -0,0 +1 @@
|
||||||
|
(what is|what's) (?P<Item>.*) (?P<RequestType>temperature|humidity|adjusted to|regulated to|tuned to)
|
|
@ -0,0 +1,3 @@
|
||||||
|
requests>=2.10.0
|
||||||
|
fuzzywuzzy==0.14.0
|
||||||
|
python-Levenshtein==0.12.0
|
|
@ -0,0 +1,3 @@
|
||||||
|
set
|
||||||
|
dim
|
||||||
|
bright
|
|
@ -0,0 +1,3 @@
|
||||||
|
turn
|
||||||
|
switch
|
||||||
|
put
|
|
@ -0,0 +1 @@
|
||||||
|
refresh open hab items
|
|
@ -0,0 +1,2 @@
|
||||||
|
regulate|adjust|tune
|
||||||
|
increase|decrease
|
|
@ -0,0 +1,2 @@
|
||||||
|
what is
|
||||||
|
what's
|
Loading…
Reference in New Issue