boneIO 0.1.5__tar.gz → 0.2.0.dev9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boneio-0.1.5 → boneio-0.2.0.dev9}/MANIFEST.in +1 -0
- {boneio-0.1.5/boneio.egg-info → boneio-0.2.0.dev9}/PKG-INFO +2 -2
- boneio-0.2.0.dev9/boneio/bonecli.py +103 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/const.py +18 -4
- boneio-0.2.0.dev9/boneio/cover.py +256 -0
- boneio-0.2.0.dev9/boneio/example_config/cover.yaml +8 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/example_config/output24x16A.yaml +77 -96
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/__init__.py +2 -0
- boneio-0.2.0.dev9/boneio/helper/events.py +111 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/ha_discovery.py +53 -6
- boneio-0.2.0.dev9/boneio/helper/loader.py +350 -0
- boneio-0.2.0.dev9/boneio/helper/state_manager.py +59 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/yaml.py +1 -1
- boneio-0.2.0.dev9/boneio/manager.py +355 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/modbus.py +44 -39
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/mqtt_client.py +17 -11
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/relay/basic.py +7 -2
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/relay/mcp.py +18 -4
- boneio-0.2.0.dev9/boneio/runner.py +115 -0
- boneio-0.2.0.dev9/boneio/schema/actions.yaml +39 -0
- boneio-0.2.0.dev9/boneio/schema/actions_sensor.yaml +5 -0
- boneio-0.2.0.dev9/boneio/schema/actions_switch.yaml +5 -0
- {boneio-0.1.5/boneio → boneio-0.2.0.dev9/boneio/schema}/schema.yaml +91 -70
- boneio-0.2.0.dev9/boneio/sensor/modbus/__init__.py +234 -0
- boneio-0.2.0.dev9/boneio/sensor/modbus/sdm120.json +122 -0
- boneio-0.2.0.dev9/boneio/sensor/modbus/sdm630.json +300 -0
- boneio-0.2.0.dev9/boneio/sensor/modbus/sofar.json +150 -0
- boneio-0.2.0.dev9/boneio/version.py +2 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9/boneio.egg-info}/PKG-INFO +2 -2
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio.egg-info/SOURCES.txt +14 -2
- boneio-0.2.0.dev9/boneio.egg-info/entry_points.txt +3 -0
- boneio-0.2.0.dev9/boneio.egg-info/requires.txt +23 -0
- boneio-0.2.0.dev9/requirements.txt +41 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/setup.py +14 -13
- boneio-0.1.5/boneio/bonecli.py +0 -161
- boneio-0.1.5/boneio/manager.py +0 -413
- boneio-0.1.5/boneio/sensor/sdm630.py +0 -198
- boneio-0.1.5/boneio/version.py +0 -2
- boneio-0.1.5/boneio.egg-info/entry_points.txt +0 -3
- boneio-0.1.5/boneio.egg-info/requires.txt +0 -22
- boneio-0.1.5/requirements.txt +0 -49
- {boneio-0.1.5 → boneio-0.2.0.dev9}/LICENSE +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/README.md +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/__init__.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/example_config/__init__.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/example_config/adc.yaml +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/example_config/config.yaml +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/example_config/input.yaml +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/example_config/output32x5A.yaml +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/fonts/danube__.ttf +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/exceptions.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/gpio.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/mqtt.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/oled.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/queue.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/helper/stats.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/input/__init__.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/input/gpio.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/oled.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/relay/__init__.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/relay/gpio.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/sensor/__init__.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/sensor/adc.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/sensor/gpio.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio/sensor/temp/__init__.py +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio.egg-info/dependency_links.txt +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/boneio.egg-info/top_level.txt +0 -0
- {boneio-0.1.5 → boneio-0.2.0.dev9}/setup.cfg +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: boneio
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0.dev9
|
|
4
4
|
Summary: Python App for BoneIO
|
|
5
5
|
Home-page: https://github.com/boneIO-eu/app_bbb
|
|
6
6
|
License: GNU General Public License v3.0
|
|
7
|
-
Download-URL: https://github.com/boneIO-eu/app_bbb/archive/0.
|
|
7
|
+
Download-URL: https://github.com/boneIO-eu/app_bbb/archive/0.2.0.dev9.zip
|
|
8
8
|
Platform: UNKNOWN
|
|
9
9
|
Classifier: Programming Language :: Python
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.7
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Bonecli script."""
|
|
2
|
+
import argparse
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from colorlog import ColoredFormatter
|
|
9
|
+
|
|
10
|
+
from boneio.const import ACTION
|
|
11
|
+
from boneio.helper import load_config_from_file
|
|
12
|
+
from boneio.runner import async_run, configure_logger
|
|
13
|
+
from boneio.version import __version__
|
|
14
|
+
|
|
15
|
+
TASK_CANCELATION_TIMEOUT = 1
|
|
16
|
+
|
|
17
|
+
_LOGGER = logging.getLogger(__name__)
|
|
18
|
+
logging.basicConfig(level=logging.INFO)
|
|
19
|
+
fmt = "%(asctime)s %(levelname)s (%(threadName)s) [%(name)s] %(message)s"
|
|
20
|
+
datefmt = "%Y-%m-%d %H:%M:%S"
|
|
21
|
+
colorfmt = f"%(log_color)s{fmt}%(reset)s"
|
|
22
|
+
logging.getLogger().handlers[0].setFormatter(
|
|
23
|
+
ColoredFormatter(
|
|
24
|
+
colorfmt,
|
|
25
|
+
datefmt=datefmt,
|
|
26
|
+
reset=True,
|
|
27
|
+
log_colors={
|
|
28
|
+
"DEBUG": "cyan",
|
|
29
|
+
"INFO": "green",
|
|
30
|
+
"WARNING": "yellow",
|
|
31
|
+
"ERROR": "red",
|
|
32
|
+
"CRITICAL": "red",
|
|
33
|
+
},
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_arguments() -> argparse.Namespace:
|
|
39
|
+
"""Get parsed passed in arguments."""
|
|
40
|
+
|
|
41
|
+
parser = argparse.ArgumentParser(
|
|
42
|
+
description="boneIO app for BeagleBone Black.",
|
|
43
|
+
)
|
|
44
|
+
parser.add_argument(ACTION, type=str, default="run")
|
|
45
|
+
parser.add_argument("--version", action="version", version=__version__)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"-c",
|
|
48
|
+
"--config",
|
|
49
|
+
metavar="path_to_config_dir",
|
|
50
|
+
default="./config.yaml",
|
|
51
|
+
help="File which contains boneIO configuration",
|
|
52
|
+
)
|
|
53
|
+
parser.add_argument(
|
|
54
|
+
"--debug", "-d", action="count", help="Start boneIO in debug mode", default=0
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--mqttusername", help="Mqtt username to use if you don't want provide in file."
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--mqttpassword", help="Mqtt password to use if you don't want provide in file."
|
|
61
|
+
)
|
|
62
|
+
arguments = parser.parse_args()
|
|
63
|
+
|
|
64
|
+
return arguments
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def run(config: str, debug: int, mqttusername: str = "", mqttpassword: str = ""):
|
|
68
|
+
"""Run BoneIO."""
|
|
69
|
+
_LOGGER.info("BoneIO starting.")
|
|
70
|
+
_config = load_config_from_file(config_file=config)
|
|
71
|
+
if not _config:
|
|
72
|
+
return
|
|
73
|
+
configure_logger(log_config=_config.get("logger"), debug=debug)
|
|
74
|
+
return asyncio.run(
|
|
75
|
+
async_run(
|
|
76
|
+
config=_config,
|
|
77
|
+
config_path=os.path.split(config),
|
|
78
|
+
mqttusername=mqttusername,
|
|
79
|
+
mqttpassword=mqttpassword,
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def main() -> int:
|
|
85
|
+
"""Start boneIO."""
|
|
86
|
+
|
|
87
|
+
args = get_arguments()
|
|
88
|
+
debug = args.debug
|
|
89
|
+
|
|
90
|
+
exit_code = 0
|
|
91
|
+
if args.action == "run":
|
|
92
|
+
exit_code = run(
|
|
93
|
+
config=args.config,
|
|
94
|
+
mqttusername=args.mqttusername,
|
|
95
|
+
mqttpassword=args.mqttpassword,
|
|
96
|
+
debug=debug,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return exit_code
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
sys.exit(main())
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# from typing import Literal
|
|
2
2
|
from datetime import timedelta
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from Adafruit_BBIO.GPIO import HIGH, LOW, BOTH, FALLING
|
|
6
|
+
except ModuleNotFoundError:
|
|
7
|
+
pass
|
|
4
8
|
from typing_extensions import Literal
|
|
5
9
|
|
|
6
10
|
BONEIO = "boneIO"
|
|
@@ -33,7 +37,8 @@ MODBUS = "modbus"
|
|
|
33
37
|
UART = "uart"
|
|
34
38
|
RX = "rx"
|
|
35
39
|
TX = "tx"
|
|
36
|
-
|
|
40
|
+
RESTORE_STATE = "restore_state"
|
|
41
|
+
MODEL = "model"
|
|
37
42
|
UARTS = {
|
|
38
43
|
"uart1": {ID: "/dev/ttyS1", TX: "P9.24", RX: "P9.26"},
|
|
39
44
|
"uart4": {ID: "/dev/ttyS4", TX: "P9.13", RX: "P9.11"},
|
|
@@ -48,7 +53,6 @@ SECOND_DELAY_DURATION = 0.3
|
|
|
48
53
|
# HA CONSTS
|
|
49
54
|
HOMEASSISTANT = "homeassistant"
|
|
50
55
|
HA_DISCOVERY = "ha_discovery"
|
|
51
|
-
HA_TYPE = "ha_type"
|
|
52
56
|
OUTPUT_TYPE = "output_type"
|
|
53
57
|
SHOW_HA = "show_in_ha"
|
|
54
58
|
|
|
@@ -85,6 +89,7 @@ USERNAME = "username"
|
|
|
85
89
|
PASSWORD = "password"
|
|
86
90
|
ONLINE = "online"
|
|
87
91
|
OFFLINE = "offline"
|
|
92
|
+
TOPIC = "topic"
|
|
88
93
|
TOPIC_PREFIX = "topic_prefix"
|
|
89
94
|
|
|
90
95
|
# I2C and MCP CONST
|
|
@@ -101,15 +106,24 @@ BINARY_SENSOR = "binary_sensor"
|
|
|
101
106
|
LM75 = "lm75"
|
|
102
107
|
MCP_TEMP_9808 = "mcp9808"
|
|
103
108
|
INPUT_SENSOR = "inputsensor"
|
|
104
|
-
SDM630 = "sdm630"
|
|
105
109
|
|
|
106
110
|
BASE = "base"
|
|
107
111
|
LENGTH = "length"
|
|
108
112
|
REGISTERS = "registers"
|
|
109
113
|
|
|
114
|
+
COVER = "cover"
|
|
115
|
+
IDLE = "idle"
|
|
116
|
+
OPENING = "opening"
|
|
117
|
+
CLOSING = "closing"
|
|
118
|
+
CLOSED = "closed"
|
|
119
|
+
OPEN = "open"
|
|
120
|
+
CLOSE = "close"
|
|
121
|
+
STOP = "stop"
|
|
122
|
+
|
|
110
123
|
# TYPING
|
|
111
124
|
ClickTypes = Literal[SINGLE, DOUBLE, LONG, PRESSED, RELEASED]
|
|
112
125
|
OledDataTypes = Literal[UPTIME, NETWORK, CPU, DISK, MEMORY, SWAP, OUTPUT]
|
|
113
126
|
Gpio_States = Literal[HIGH, LOW]
|
|
114
127
|
Gpio_Edges = Literal[BOTH, FALLING]
|
|
115
128
|
InputTypes = Literal[INPUT, INPUT_SENSOR]
|
|
129
|
+
DEVICE_CLASS = "device_class"
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Cover module."""
|
|
2
|
+
import asyncio
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Any, Callable
|
|
5
|
+
from boneio.const import CLOSE, COVER, IDLE, OPEN, OPENING, CLOSING, CLOSED, STOP
|
|
6
|
+
from boneio.helper.events import EventBus
|
|
7
|
+
from boneio.helper.mqtt import BasicMqtt
|
|
8
|
+
from boneio.relay import MCPRelay
|
|
9
|
+
|
|
10
|
+
_LOGGER = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
COVER_COMMANDS = {
|
|
13
|
+
OPEN: "open_cover",
|
|
14
|
+
CLOSE: "close_cover",
|
|
15
|
+
STOP: "stop",
|
|
16
|
+
"toggle": "toggle",
|
|
17
|
+
"toggle_open": "toggle_open",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class RelayHelper:
|
|
22
|
+
"""Relay helper for cover either open/close."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, relay: MCPRelay, time: int) -> None:
|
|
25
|
+
"""Initialize helper."""
|
|
26
|
+
self._relay = relay
|
|
27
|
+
self._steps = 100 / time
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def relay(self) -> MCPRelay:
|
|
31
|
+
"""Get relay."""
|
|
32
|
+
return self._relay
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def steps(self) -> int:
|
|
36
|
+
"""Get steps for each time."""
|
|
37
|
+
return self._steps
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Cover(BasicMqtt):
|
|
41
|
+
"""Cover class of boneIO"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
id: str,
|
|
46
|
+
open_relay: Any,
|
|
47
|
+
close_relay: MCPRelay,
|
|
48
|
+
state_save: Callable,
|
|
49
|
+
open_time: int,
|
|
50
|
+
close_time: int,
|
|
51
|
+
event_bus: EventBus,
|
|
52
|
+
restored_state: int = 100,
|
|
53
|
+
**kwargs,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Initialize cover class."""
|
|
56
|
+
self._loop = asyncio.get_event_loop()
|
|
57
|
+
self._id = id
|
|
58
|
+
super().__init__(id=id, name=id, topic_type=COVER, **kwargs)
|
|
59
|
+
self._lock = asyncio.Lock()
|
|
60
|
+
self._state_save = state_save
|
|
61
|
+
self._open = RelayHelper(relay=open_relay, time=open_time)
|
|
62
|
+
self._close = RelayHelper(relay=close_relay, time=close_time)
|
|
63
|
+
self._set_position = None
|
|
64
|
+
self._current_operation = IDLE
|
|
65
|
+
self._position = restored_state
|
|
66
|
+
self._requested_closing = True
|
|
67
|
+
self._event_bus = event_bus
|
|
68
|
+
self._timer_handle = None
|
|
69
|
+
if self._position is None:
|
|
70
|
+
self._closed = True
|
|
71
|
+
else:
|
|
72
|
+
self._closed = self._position <= 0
|
|
73
|
+
self._event_bus.add_sigterm_listener(self.on_exit)
|
|
74
|
+
self._loop.call_soon_threadsafe(
|
|
75
|
+
self._loop.call_later,
|
|
76
|
+
0.5,
|
|
77
|
+
self.send_state,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
async def run_cover(
|
|
81
|
+
self,
|
|
82
|
+
current_operation: str,
|
|
83
|
+
) -> None:
|
|
84
|
+
"""Run cover engine."""
|
|
85
|
+
if self._current_operation != IDLE:
|
|
86
|
+
self._stop_cover()
|
|
87
|
+
self._current_operation = current_operation
|
|
88
|
+
|
|
89
|
+
def get_relays():
|
|
90
|
+
if current_operation == OPENING:
|
|
91
|
+
return (self._open.relay, self._close.relay)
|
|
92
|
+
else:
|
|
93
|
+
return (self._close.relay, self._open.relay)
|
|
94
|
+
|
|
95
|
+
(relay, inverted_relay) = get_relays()
|
|
96
|
+
async with self._lock:
|
|
97
|
+
if inverted_relay.is_active:
|
|
98
|
+
inverted_relay.turn_off()
|
|
99
|
+
self._timer_handle = self._event_bus.add_listener(
|
|
100
|
+
f"{COVER}{self.id}", self.listen_cover
|
|
101
|
+
)
|
|
102
|
+
relay.turn_on()
|
|
103
|
+
|
|
104
|
+
def on_exit(self) -> None:
|
|
105
|
+
"""Stop on exit."""
|
|
106
|
+
self._stop_cover(on_exit=True)
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def cover_state(self):
|
|
110
|
+
"""Current state of cover."""
|
|
111
|
+
return CLOSED if self._closed else OPEN
|
|
112
|
+
|
|
113
|
+
def stop(self):
|
|
114
|
+
"""Public Stop cover graceful."""
|
|
115
|
+
_LOGGER.info("Stopping cover %s.", self._id)
|
|
116
|
+
if self._current_operation != IDLE:
|
|
117
|
+
self._stop_cover(on_exit=False)
|
|
118
|
+
|
|
119
|
+
def send_state(self):
|
|
120
|
+
"""Send state of cover to mqtt."""
|
|
121
|
+
self._send_message(topic=f"{self._send_topic}/state", payload=self.cover_state)
|
|
122
|
+
pos = round(self._position, 0)
|
|
123
|
+
self._send_message(topic=f"{self._send_topic}/pos", payload=str(pos))
|
|
124
|
+
self._state_save(position=pos)
|
|
125
|
+
|
|
126
|
+
def _stop_cover(self, on_exit=False):
|
|
127
|
+
"""Stop cover."""
|
|
128
|
+
self._open.relay.turn_off()
|
|
129
|
+
self._close.relay.turn_off()
|
|
130
|
+
if self._timer_handle is not None:
|
|
131
|
+
self._event_bus.remove_listener(f"{COVER}{self.id}")
|
|
132
|
+
self._timer_handle = None
|
|
133
|
+
self._set_position = None
|
|
134
|
+
if not on_exit:
|
|
135
|
+
self.send_state()
|
|
136
|
+
self._current_operation = IDLE
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def current_cover_position(self):
|
|
140
|
+
"""Return the current position of the cover."""
|
|
141
|
+
return round(self._position, 0)
|
|
142
|
+
|
|
143
|
+
def listen_cover(self, *args):
|
|
144
|
+
"""Listen for change in cover."""
|
|
145
|
+
if self._current_operation == IDLE:
|
|
146
|
+
return
|
|
147
|
+
|
|
148
|
+
def get_step():
|
|
149
|
+
"""Get step for current operation."""
|
|
150
|
+
if self._requested_closing:
|
|
151
|
+
return -self._close.steps
|
|
152
|
+
else:
|
|
153
|
+
return self._open.steps
|
|
154
|
+
|
|
155
|
+
step = get_step()
|
|
156
|
+
self._position += step
|
|
157
|
+
rounded_pos = round(self._position, 0)
|
|
158
|
+
if self._set_position:
|
|
159
|
+
# Set position is only working for every 10%, so round to nearest 10.
|
|
160
|
+
# Except for start moving time
|
|
161
|
+
if (self._requested_closing and rounded_pos < 95) or rounded_pos > 5:
|
|
162
|
+
rounded_pos = round(self._position, -1)
|
|
163
|
+
else:
|
|
164
|
+
if rounded_pos > 100:
|
|
165
|
+
rounded_pos = 100
|
|
166
|
+
elif rounded_pos < 0:
|
|
167
|
+
rounded_pos = 0
|
|
168
|
+
self._send_message(topic=f"{self._send_topic}/pos", payload=rounded_pos)
|
|
169
|
+
if rounded_pos == self._set_position or (
|
|
170
|
+
self._set_position is None and (rounded_pos >= 100 or rounded_pos <= 0)
|
|
171
|
+
):
|
|
172
|
+
self._position = rounded_pos
|
|
173
|
+
self._closed = self.current_cover_position <= 0
|
|
174
|
+
self._stop_cover()
|
|
175
|
+
return
|
|
176
|
+
|
|
177
|
+
self._closed = self.current_cover_position <= 0
|
|
178
|
+
|
|
179
|
+
async def close_cover(self):
|
|
180
|
+
"""Close cover."""
|
|
181
|
+
if self._position == 0:
|
|
182
|
+
return
|
|
183
|
+
if self._position is None:
|
|
184
|
+
self._closed = True
|
|
185
|
+
return
|
|
186
|
+
_LOGGER.info("Closing cover %s.", self._id)
|
|
187
|
+
|
|
188
|
+
self._requested_closing = True
|
|
189
|
+
self._send_message(topic=f"{self._send_topic}/state", payload=CLOSING)
|
|
190
|
+
await self.run_cover(
|
|
191
|
+
current_operation=CLOSING,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
async def open_cover(self):
|
|
195
|
+
"""Open cover."""
|
|
196
|
+
if self._position == 100:
|
|
197
|
+
return
|
|
198
|
+
if self._position is None:
|
|
199
|
+
self._closed = False
|
|
200
|
+
return
|
|
201
|
+
_LOGGER.info("Opening cover %s.", self._id)
|
|
202
|
+
|
|
203
|
+
self._requested_closing = False
|
|
204
|
+
self._send_message(topic=f"{self._send_topic}/state", payload=OPENING)
|
|
205
|
+
await self.run_cover(
|
|
206
|
+
current_operation=OPENING,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
async def set_cover_position(self, position: int):
|
|
210
|
+
"""Move cover to a specific position."""
|
|
211
|
+
set_position = round(position, -1)
|
|
212
|
+
if self._position == position or set_position == self._set_position:
|
|
213
|
+
return
|
|
214
|
+
if self._set_position:
|
|
215
|
+
self._stop_cover(on_exit=True)
|
|
216
|
+
_LOGGER.info("Setting cover at position %s.", set_position)
|
|
217
|
+
self._set_position = set_position
|
|
218
|
+
|
|
219
|
+
self._requested_closing = set_position < self._position
|
|
220
|
+
current_operation = CLOSING if self._requested_closing else OPENING
|
|
221
|
+
_LOGGER.debug(
|
|
222
|
+
"Requested set position %s. Operation %s", set_position, current_operation
|
|
223
|
+
)
|
|
224
|
+
self._send_message(topic=f"{self._send_topic}/state", payload=current_operation)
|
|
225
|
+
await self.run_cover(
|
|
226
|
+
current_operation=current_operation,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
def open(self):
|
|
230
|
+
_LOGGER.debug("Opening cover %s.", self._id)
|
|
231
|
+
asyncio.create_task(self.open_cover())
|
|
232
|
+
|
|
233
|
+
def close(self):
|
|
234
|
+
_LOGGER.debug("Closing cover %s.", self._id)
|
|
235
|
+
asyncio.create_task(self.close_cover())
|
|
236
|
+
|
|
237
|
+
def toggle(self):
|
|
238
|
+
_LOGGER.debug("Toggle cover %s from input.", self._id)
|
|
239
|
+
if self.cover_state == CLOSED:
|
|
240
|
+
self.close()
|
|
241
|
+
else:
|
|
242
|
+
self.open()
|
|
243
|
+
|
|
244
|
+
def toggle_open(self):
|
|
245
|
+
_LOGGER.debug("Toggle open cover %s from input.", self._id)
|
|
246
|
+
if self._current_operation != IDLE:
|
|
247
|
+
self.stop()
|
|
248
|
+
else:
|
|
249
|
+
self.open()
|
|
250
|
+
|
|
251
|
+
def toggle_close(self):
|
|
252
|
+
_LOGGER.debug("Toggle close cover %s from input.", self._id)
|
|
253
|
+
if self._current_operation != IDLE:
|
|
254
|
+
self.stop()
|
|
255
|
+
else:
|
|
256
|
+
self.close()
|
|
@@ -1,139 +1,120 @@
|
|
|
1
|
-
|
|
2
|
-
- id: mcp1-gpa0
|
|
1
|
+
- id: OUT_01
|
|
3
2
|
kind: mcp
|
|
4
|
-
mcp_id:
|
|
5
|
-
pin:
|
|
6
|
-
|
|
7
|
-
- id:
|
|
3
|
+
mcp_id: mcp2
|
|
4
|
+
pin: 9
|
|
5
|
+
output_type: light
|
|
6
|
+
- id: OUT_02
|
|
7
|
+
kind: mcp
|
|
8
|
+
mcp_id: mcp2
|
|
9
|
+
pin: 8
|
|
10
|
+
output_type: light
|
|
11
|
+
- id: OUT_03
|
|
8
12
|
kind: mcp
|
|
9
13
|
mcp_id: mcp1
|
|
10
14
|
pin: 1
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- id: mcp1-gpb0
|
|
15
|
+
output_type: light
|
|
16
|
+
- id: OUT_04
|
|
14
17
|
kind: mcp
|
|
15
18
|
mcp_id: mcp1
|
|
16
|
-
pin:
|
|
17
|
-
|
|
18
|
-
- id:
|
|
19
|
+
pin: 0
|
|
20
|
+
output_type: switch
|
|
21
|
+
- id: OUT_05
|
|
19
22
|
kind: mcp
|
|
20
|
-
mcp_id:
|
|
21
|
-
pin:
|
|
22
|
-
|
|
23
|
-
- id:
|
|
23
|
+
mcp_id: mcp2
|
|
24
|
+
pin: 13
|
|
25
|
+
output_type: light
|
|
26
|
+
- id: OUT_06
|
|
24
27
|
kind: mcp
|
|
25
|
-
mcp_id:
|
|
26
|
-
pin:
|
|
27
|
-
|
|
28
|
-
- id:
|
|
28
|
+
mcp_id: mcp2
|
|
29
|
+
pin: 12
|
|
30
|
+
output_type: light
|
|
31
|
+
- id: OUT_07
|
|
29
32
|
kind: mcp
|
|
30
|
-
mcp_id:
|
|
33
|
+
mcp_id: mcp2
|
|
31
34
|
pin: 11
|
|
32
|
-
|
|
33
|
-
- id:
|
|
35
|
+
output_type: light
|
|
36
|
+
- id: OUT_08
|
|
37
|
+
kind: mcp
|
|
38
|
+
mcp_id: mcp2
|
|
39
|
+
pin: 10
|
|
40
|
+
output_type: light
|
|
41
|
+
- id: OUT_09
|
|
34
42
|
kind: mcp
|
|
35
43
|
mcp_id: mcp1
|
|
36
|
-
pin:
|
|
37
|
-
|
|
38
|
-
- id:
|
|
44
|
+
pin: 14
|
|
45
|
+
output_type: light
|
|
46
|
+
- id: OUT_10
|
|
39
47
|
kind: mcp
|
|
40
48
|
mcp_id: mcp1
|
|
41
|
-
pin:
|
|
42
|
-
|
|
43
|
-
- id:
|
|
49
|
+
pin: 15
|
|
50
|
+
output_type: light
|
|
51
|
+
- id: OUT_11
|
|
44
52
|
kind: mcp
|
|
45
53
|
mcp_id: mcp1
|
|
46
|
-
pin:
|
|
47
|
-
|
|
48
|
-
- id:
|
|
54
|
+
pin: 13
|
|
55
|
+
output_type: light
|
|
56
|
+
- id: OUT_12
|
|
49
57
|
kind: mcp
|
|
50
58
|
mcp_id: mcp1
|
|
51
|
-
pin:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- id: mcp2-gpa0
|
|
59
|
+
pin: 12
|
|
60
|
+
output_type: light
|
|
61
|
+
- id: OUT_13
|
|
68
62
|
kind: mcp
|
|
69
63
|
mcp_id: mcp2
|
|
70
|
-
pin:
|
|
71
|
-
|
|
72
|
-
- id:
|
|
64
|
+
pin: 6
|
|
65
|
+
output_type: light
|
|
66
|
+
- id: OUT_14
|
|
73
67
|
kind: mcp
|
|
74
68
|
mcp_id: mcp2
|
|
75
|
-
pin:
|
|
76
|
-
|
|
77
|
-
- id:
|
|
69
|
+
pin: 5
|
|
70
|
+
output_type: light
|
|
71
|
+
- id: OUT_15
|
|
78
72
|
kind: mcp
|
|
79
73
|
mcp_id: mcp2
|
|
80
|
-
pin:
|
|
81
|
-
|
|
82
|
-
- id:
|
|
74
|
+
pin: 4
|
|
75
|
+
output_type: light
|
|
76
|
+
- id: OUT_16
|
|
83
77
|
kind: mcp
|
|
84
78
|
mcp_id: mcp2
|
|
85
79
|
pin: 3
|
|
86
|
-
|
|
87
|
-
- id:
|
|
80
|
+
output_type: light
|
|
81
|
+
- id: OUT_17
|
|
88
82
|
kind: mcp
|
|
89
83
|
mcp_id: mcp2
|
|
90
|
-
pin:
|
|
91
|
-
|
|
92
|
-
- id:
|
|
84
|
+
pin: 2
|
|
85
|
+
output_type: light
|
|
86
|
+
- id: OUT_18
|
|
93
87
|
kind: mcp
|
|
94
88
|
mcp_id: mcp2
|
|
95
|
-
pin:
|
|
96
|
-
|
|
97
|
-
- id:
|
|
89
|
+
pin: 0
|
|
90
|
+
output_type: light
|
|
91
|
+
- id: OUT_19
|
|
98
92
|
kind: mcp
|
|
99
93
|
mcp_id: mcp2
|
|
100
|
-
pin:
|
|
101
|
-
|
|
102
|
-
- id:
|
|
94
|
+
pin: 1
|
|
95
|
+
output_type: light
|
|
96
|
+
- id: OUT_20
|
|
103
97
|
kind: mcp
|
|
104
98
|
mcp_id: mcp2
|
|
105
99
|
pin: 7
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- id: mcp2-gpb0
|
|
100
|
+
output_type: light
|
|
101
|
+
- id: OUT_21
|
|
110
102
|
kind: mcp
|
|
111
|
-
mcp_id:
|
|
103
|
+
mcp_id: mcp1
|
|
112
104
|
pin: 8
|
|
113
|
-
|
|
114
|
-
- id:
|
|
105
|
+
output_type: light
|
|
106
|
+
- id: OUT_22
|
|
115
107
|
kind: mcp
|
|
116
|
-
mcp_id:
|
|
108
|
+
mcp_id: mcp1
|
|
117
109
|
pin: 9
|
|
118
|
-
|
|
119
|
-
- id:
|
|
110
|
+
output_type: light
|
|
111
|
+
- id: OUT_23
|
|
120
112
|
kind: mcp
|
|
121
|
-
mcp_id:
|
|
122
|
-
pin: 10
|
|
123
|
-
ha_type: switch
|
|
124
|
-
- id: mcp2-gpb3
|
|
125
|
-
kind: mcp
|
|
126
|
-
mcp_id: mcp2
|
|
113
|
+
mcp_id: mcp1
|
|
127
114
|
pin: 11
|
|
128
|
-
|
|
129
|
-
- id:
|
|
115
|
+
output_type: light
|
|
116
|
+
- id: OUT_24
|
|
130
117
|
kind: mcp
|
|
131
|
-
mcp_id:
|
|
132
|
-
pin:
|
|
133
|
-
|
|
134
|
-
- id: mcp2-gpb5
|
|
135
|
-
kind: mcp
|
|
136
|
-
mcp_id: mcp2
|
|
137
|
-
pin: 13
|
|
138
|
-
ha_type: switch
|
|
139
|
-
|
|
118
|
+
mcp_id: mcp1
|
|
119
|
+
pin: 10
|
|
120
|
+
output_type: light
|
|
@@ -18,6 +18,7 @@ from boneio.helper.yaml import (
|
|
|
18
18
|
load_config_from_string,
|
|
19
19
|
load_config_from_file,
|
|
20
20
|
)
|
|
21
|
+
from boneio.helper.state_manager import StateManager
|
|
21
22
|
from boneio.helper.ha_discovery import (
|
|
22
23
|
ha_relay_availabilty_message,
|
|
23
24
|
ha_sensor_temp_availabilty_message,
|
|
@@ -50,6 +51,7 @@ __all__ = [
|
|
|
50
51
|
"GPIOInputException",
|
|
51
52
|
"I2CError",
|
|
52
53
|
"GpioBaseClass",
|
|
54
|
+
"StateManager",
|
|
53
55
|
"configure_pin",
|
|
54
56
|
"BasicMqtt",
|
|
55
57
|
"UniqueQueue",
|