boneIO 0.1.0.dev13__tar.gz → 0.1.0.dev15__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.
Files changed (43) hide show
  1. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/PKG-INFO +2 -2
  2. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/bonecli.py +11 -10
  3. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/const.py +55 -29
  4. boneio-0.1.0.dev15/boneio/helper/__init__.py +41 -0
  5. boneio-0.1.0.dev15/boneio/helper/exceptions.py +13 -0
  6. boneio-0.1.0.dev15/boneio/helper/gpio.py +79 -0
  7. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/helper/ha_discovery.py +21 -2
  8. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/helper/oled.py +1 -1
  9. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/helper/stats.py +3 -4
  10. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/helper/yaml.py +1 -1
  11. boneio-0.1.0.dev15/boneio/input/__init__.py +5 -0
  12. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/input/gpio.py +10 -36
  13. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/manager.py +110 -53
  14. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/mqtt_client.py +1 -1
  15. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/oled.py +3 -4
  16. boneio-0.1.0.dev15/boneio/relay/__init__.py +5 -0
  17. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/relay/basic.py +1 -1
  18. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/relay/gpio.py +3 -2
  19. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/relay/mcp.py +1 -1
  20. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/schema.yaml +38 -1
  21. boneio-0.1.0.dev15/boneio/sensor/__init__.py +5 -0
  22. boneio-0.1.0.dev15/boneio/sensor/gpio.py +32 -0
  23. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/sensor/lm75.py +9 -4
  24. boneio-0.1.0.dev15/boneio/version.py +2 -0
  25. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio.egg-info/PKG-INFO +2 -2
  26. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio.egg-info/SOURCES.txt +2 -0
  27. boneio-0.1.0.dev13/boneio/helper/__init__.py +0 -23
  28. boneio-0.1.0.dev13/boneio/helper/gpio.py +0 -30
  29. boneio-0.1.0.dev13/boneio/input/__init__.py +0 -5
  30. boneio-0.1.0.dev13/boneio/relay/__init__.py +0 -5
  31. boneio-0.1.0.dev13/boneio/sensor/__init__.py +0 -4
  32. boneio-0.1.0.dev13/boneio/version.py +0 -2
  33. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/MANIFEST.in +0 -0
  34. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/README.md +0 -0
  35. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/__init__.py +0 -0
  36. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio/fonts/danube__.ttf +0 -0
  37. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio.egg-info/dependency_links.txt +0 -0
  38. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio.egg-info/entry_points.txt +0 -0
  39. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio.egg-info/requires.txt +0 -0
  40. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/boneio.egg-info/top_level.txt +0 -0
  41. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/requirements.txt +0 -0
  42. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/setup.cfg +0 -0
  43. {boneio-0.1.0.dev13 → boneio-0.1.0.dev15}/setup.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: boneio
3
- Version: 0.1.0.dev13
3
+ Version: 0.1.0.dev15
4
4
  Summary: Python Helper for BoneIO
5
5
  Home-page: https://github.com/maciejk1984/boneIO
6
6
  License: GNU General Public License v3.0
7
- Download-URL: https://github.com/maciejk1984/boneIO/archive/0.1.0.dev13.zip
7
+ Download-URL: https://github.com/maciejk1984/boneIO/archive/0.1.0.dev15.zip
8
8
  Platform: UNKNOWN
9
9
  Classifier: Programming Language :: Python
10
10
  Classifier: Programming Language :: Python :: 3.7
@@ -6,9 +6,9 @@ from functools import wraps
6
6
  import click
7
7
  from colorlog import ColoredFormatter
8
8
 
9
- from .const import (
9
+ from boneio.const import (
10
10
  ENABLED,
11
- GPIO_INPUT,
11
+ INPUT,
12
12
  HA_DISCOVERY,
13
13
  HOST,
14
14
  MCP23017,
@@ -19,11 +19,12 @@ from .const import (
19
19
  PASSWORD,
20
20
  TOPIC_PREFIX,
21
21
  USERNAME,
22
+ LM75,
22
23
  )
23
- from .helper import CustomValidator, load_yaml_file
24
- from .manager import Manager
25
- from .mqtt_client import MQTTClient
26
- from .version import __version__
24
+ from boneio.helper import CustomValidator, load_yaml_file
25
+ from boneio.manager import Manager
26
+ from boneio.mqtt_client import MQTTClient
27
+ from boneio.version import __version__
27
28
 
28
29
  _LOGGER = logging.getLogger(__name__)
29
30
  logging.basicConfig(level=logging.INFO)
@@ -133,12 +134,12 @@ async def run(ctx, debug: int, config: str, mqttpassword: str = ""):
133
134
  manager = Manager(
134
135
  send_message=client.send_message,
135
136
  topic_prefix=_config[MQTT][TOPIC_PREFIX],
136
- relay_pins=_config[OUTPUT],
137
- input_pins=_config[GPIO_INPUT],
137
+ relay_pins=_config.get(OUTPUT, []),
138
+ input_pins=_config.get(INPUT, []),
138
139
  ha_discovery=_config[MQTT][HA_DISCOVERY][ENABLED],
139
140
  ha_discovery_prefix=_config[MQTT][HA_DISCOVERY][TOPIC_PREFIX],
140
- mcp23017=_config[MCP23017],
141
- lm75=_config.get("lm75"),
141
+ mcp23017=_config.get(MCP23017, []),
142
+ lm75=_config.get(LM75),
142
143
  oled=_config.get(OLED),
143
144
  )
144
145
  tasks = set()
@@ -1,31 +1,15 @@
1
1
  # from typing import Literal
2
2
  from datetime import timedelta
3
-
3
+ from Adafruit_BBIO.GPIO import HIGH, LOW, BOTH, FALLING
4
4
  from typing_extensions import Literal
5
5
 
6
- DEBOUNCE_DURATION = timedelta(seconds=0.2)
7
- LONG_PRESS_DURATION = timedelta(seconds=0.7)
8
- DELAY_DURATION = 0.1
9
- SECOND_DELAY_DURATION = 0.3
6
+
7
+ # MISCELLANEOUS CONSTS
10
8
  RELAY = "relay"
11
- SINGLE = "single"
12
- DOUBLE = "double"
13
- LONG = "long"
14
- ONLINE = "online"
15
9
  ON = "ON"
16
10
  OFF = "OFF"
17
11
  STATE = "state"
18
- PAHO = "paho.mqtt.client"
19
- ClickTypes = Literal[SINGLE, DOUBLE, LONG]
20
- MQTT = "mqtt"
21
- HOST = "host"
22
- USERNAME = "username"
23
- PASSWORD = "password"
24
- TOPIC_PREFIX = "topic_prefix"
25
- HOMEASSISTANT = "homeassistant"
26
- HA_DISCOVERY = "ha_discovery"
27
12
  ENABLED = "enabled"
28
- GPIO_INPUT = "gpio_input"
29
13
  OUTPUT = "output"
30
14
  PIN = "pin"
31
15
  ID = "id"
@@ -34,17 +18,27 @@ GPIO = "gpio"
34
18
  ACTIONS = "actions"
35
19
  ACTION = "action"
36
20
  OUTPUT = "output"
37
- ADDRESS = "address"
38
- MCP23017 = "mcp23017"
39
21
  SWITCH = "switch"
40
22
  CONFIG_PIN = "/usr/bin/config-pin"
41
- MCP = "mcp"
42
- MCP_ID = "mcp_id"
23
+
24
+ # TIMINGS FOR BUTTONS
25
+ DEBOUNCE_DURATION = timedelta(seconds=0.2)
26
+ LONG_PRESS_DURATION = timedelta(seconds=0.7)
27
+ DELAY_DURATION = 0.1
28
+ SECOND_DELAY_DURATION = 0.3
29
+
30
+ # HA CONSTS
31
+ HOMEASSISTANT = "homeassistant"
32
+ HA_DISCOVERY = "ha_discovery"
43
33
  HA_TYPE = "ha_type"
34
+ SHOW_HA = "show_in_ha"
35
+
36
+ # OLED CONST
37
+ OLED = "oled"
38
+ FONTS = "fonts"
39
+ OLED_PIN = "P9_41"
44
40
  GIGABYTE = 1073741824
45
41
  MEGABYTE = 1048576
46
- OLED_PIN = "P9_41"
47
- NUM_OF_SCREENS = 6
48
42
  WIDTH = 128
49
43
  UPTIME = "uptime"
50
44
  NETWORK = "network"
@@ -53,10 +47,42 @@ DISK = "disk"
53
47
  MEMORY = "memory"
54
48
  SWAP = "swap"
55
49
  WHITE = "white"
56
- OLED = "oled"
57
- FONTS = "fonts"
58
- OledDataTypes = Literal[UPTIME, NETWORK, CPU, DISK, MEMORY, SWAP, OUTPUT]
59
- INIT_SLEEP = "init_sleep"
50
+
51
+ # INPUT CONST
60
52
  INPUT = "input"
53
+ SINGLE = "single"
54
+ DOUBLE = "double"
55
+ LONG = "long"
56
+ PRESSED = "pressed"
57
+ RELEASED = "released"
58
+
59
+
60
+ # MQTT CONST
61
+ PAHO = "paho.mqtt.client"
62
+ MQTT = "mqtt"
63
+ HOST = "host"
64
+ USERNAME = "username"
65
+ PASSWORD = "password"
66
+ ONLINE = "online"
67
+ TOPIC_PREFIX = "topic_prefix"
68
+
69
+ # I2C and MCP CONST
70
+ ADDRESS = "address"
71
+ MCP23017 = "mcp23017"
72
+ MCP = "mcp"
73
+ MCP_ID = "mcp_id"
74
+ INIT_SLEEP = "init_sleep"
75
+
76
+ # SENSOR CONST
61
77
  TEMPERATURE = "temperature"
62
78
  SENSOR = "sensor"
79
+ BINARY_SENSOR = "binary_sensor"
80
+ LM75 = "lm75"
81
+ INPUT_SENSOR = "inputsensor"
82
+
83
+ # TYPING
84
+ ClickTypes = Literal[SINGLE, DOUBLE, LONG, PRESSED, RELEASED]
85
+ OledDataTypes = Literal[UPTIME, NETWORK, CPU, DISK, MEMORY, SWAP, OUTPUT]
86
+ Gpio_States = Literal[HIGH, LOW]
87
+ Gpio_Edges = Literal[BOTH, FALLING]
88
+ InputTypes = Literal[INPUT, INPUT_SENSOR]
@@ -0,0 +1,41 @@
1
+ """Helper dir for BoneIO."""
2
+ from boneio.helper.gpio import (
3
+ edge_detect,
4
+ setup_input,
5
+ setup_output,
6
+ read_input,
7
+ write_output,
8
+ GpioBaseClass,
9
+ configure_pin,
10
+ )
11
+ from boneio.helper.oled import make_font
12
+ from boneio.helper.stats import HostData, host_stats
13
+ from boneio.helper.yaml import CustomValidator, load_yaml_file
14
+ from boneio.helper.ha_discovery import (
15
+ ha_relay_availibilty_message,
16
+ ha_sensor_availibilty_message,
17
+ ha_sensor_temp_availibilty_message,
18
+ ha_binary_sensor_availibilty_message,
19
+ )
20
+ from boneio.helper.exceptions import GPIOInputException, I2CError
21
+
22
+ __all__ = [
23
+ "CustomValidator",
24
+ "load_yaml_file",
25
+ "HostData",
26
+ "host_stats",
27
+ "setup_input",
28
+ "setup_output",
29
+ "edge_detect",
30
+ "read_input",
31
+ "write_output",
32
+ "make_font",
33
+ "ha_relay_availibilty_message",
34
+ "ha_sensor_availibilty_message",
35
+ "ha_sensor_temp_availibilty_message",
36
+ "ha_binary_sensor_availibilty_message",
37
+ "GPIOInputException",
38
+ "I2CError",
39
+ "GpioBaseClass",
40
+ "configure_pin",
41
+ ]
@@ -0,0 +1,13 @@
1
+ """BoneIO Errors"""
2
+
3
+
4
+ class BoneIOException(Exception):
5
+ """BoneIO standard exception."""
6
+
7
+
8
+ class GPIOInputException(BoneIOException):
9
+ """GPIOInput Exception."""
10
+
11
+
12
+ class I2CError(BoneIOException):
13
+ """I2C Exception."""
@@ -0,0 +1,79 @@
1
+ import asyncio
2
+ import logging
3
+ from Adafruit_BBIO import GPIO
4
+
5
+ from boneio.helper.exceptions import GPIOInputException
6
+ from boneio.const import LOW, FALLING, Gpio_Edges, Gpio_States
7
+ from typing import Callable
8
+ import subprocess
9
+
10
+ from boneio.const import (
11
+ CONFIG_PIN,
12
+ GPIO as GPIO_STR,
13
+ ClickTypes,
14
+ )
15
+
16
+ _LOGGER = logging.getLogger(__name__)
17
+
18
+
19
+ def configure_pin(pin: str) -> None:
20
+ pin = f"{pin[0:3]}0{pin[3]}" if len(pin) == 4 else pin
21
+ _LOGGER.debug(f"Configuring pin for GPIO {pin}")
22
+ subprocess.run(
23
+ [CONFIG_PIN, pin, GPIO_STR],
24
+ stdout=subprocess.DEVNULL,
25
+ stderr=subprocess.STDOUT,
26
+ timeout=1,
27
+ )
28
+
29
+
30
+ def setup_output(pin: str):
31
+ """Set up a GPIO as output."""
32
+
33
+ GPIO.setup(pin, GPIO.OUT, pull_up_down=GPIO.PUD_DOWN)
34
+
35
+
36
+ def setup_input(pin: str, pull_mode: str = "UP"):
37
+ """Set up a GPIO as input."""
38
+ try:
39
+ GPIO.setup(pin, GPIO.IN, GPIO.PUD_DOWN if pull_mode == "DOWN" else GPIO.PUD_UP)
40
+ except (ValueError, SystemError) as err:
41
+ raise GPIOInputException(err)
42
+
43
+
44
+ def write_output(pin: str, value: str):
45
+ """Write a value to a GPIO."""
46
+
47
+ GPIO.output(pin, value)
48
+
49
+
50
+ def read_input(pin: str, on_state: Gpio_States = LOW):
51
+ """Read a value from a GPIO."""
52
+ return GPIO.input(pin) is on_state
53
+
54
+
55
+ def edge_detect(pin: str, callback: Callable, bounce: int, edge: Gpio_Edges = FALLING):
56
+ """Add detection for RISING and FALLING events."""
57
+ try:
58
+ GPIO.add_event_detect(gpio=pin, edge=edge, callback=callback, bouncetime=bounce)
59
+ except RuntimeError as err:
60
+ raise GPIOInputException(err)
61
+
62
+
63
+ class GpioBaseClass:
64
+ """Base class for initialize GPIO"""
65
+
66
+ def __init__(
67
+ self, pin: str, press_callback: Callable[[ClickTypes, str], None], **kwargs
68
+ ) -> None:
69
+ """Setup GPIO Input Button"""
70
+ self._pin = pin
71
+ configure_pin(pin)
72
+ self._loop = asyncio.get_running_loop()
73
+ self._press_callback = press_callback
74
+ setup_input(self._pin)
75
+
76
+ @property
77
+ def is_pressed(self):
78
+ """Is button pressed."""
79
+ return read_input(self._pin)
@@ -1,7 +1,7 @@
1
- from ..version import __version__
1
+ from boneio.version import __version__
2
2
 
3
3
 
4
- from ..const import INPUT, OFF, ON, RELAY, STATE, SENSOR
4
+ from boneio.const import INPUT, OFF, ON, RELAY, STATE, SENSOR, INPUT_SENSOR
5
5
 
6
6
 
7
7
  def ha_relay_availibilty_message(id: str, name: str, topic: str = "boneio"):
@@ -43,6 +43,25 @@ def ha_sensor_availibilty_message(id: str, name: str, topic: str = "boneio"):
43
43
  }
44
44
 
45
45
 
46
+ def ha_binary_sensor_availibilty_message(id: str, name: str, topic: str = "boneio"):
47
+ """Create availability topic for HA."""
48
+ return {
49
+ "availability": [{"topic": f"{topic}/{STATE}"}],
50
+ "device": {
51
+ "identifiers": [topic],
52
+ "manufacturer": "BoneIO",
53
+ "model": "BoneIO Relay Board",
54
+ "name": f"BoneIO {topic}",
55
+ "sw_version": __version__,
56
+ },
57
+ "payload_on": "pressed",
58
+ "payload_off": "released",
59
+ "name": name,
60
+ "state_topic": f"{topic}/{INPUT_SENSOR}/{id}",
61
+ "unique_id": f"{topic}{INPUT_SENSOR}{id}",
62
+ }
63
+
64
+
46
65
  def ha_sensor_temp_availibilty_message(id: str, name: str, topic: str = "boneio"):
47
66
  """Create availability topic for HA."""
48
67
  return {
@@ -2,7 +2,7 @@ import os
2
2
 
3
3
  from PIL import ImageFont
4
4
 
5
- from ..const import FONTS
5
+ from boneio.const import FONTS
6
6
 
7
7
 
8
8
  def make_font(name: str, size: int, local: bool = False):
@@ -7,7 +7,7 @@ from typing import Callable
7
7
 
8
8
  import psutil
9
9
 
10
- from ..const import (
10
+ from boneio.const import (
11
11
  CPU,
12
12
  DISK,
13
13
  GIGABYTE,
@@ -16,10 +16,9 @@ from ..const import (
16
16
  MEMORY,
17
17
  NETWORK,
18
18
  SWAP,
19
- TEMPERATURE,
20
19
  UPTIME,
21
20
  )
22
- from ..sensor.lm75 import LM75
21
+ from boneio.sensor import LM75Sensor
23
22
 
24
23
  intervals = (("d", 86400), ("h", 3600), ("m", 60))
25
24
 
@@ -132,7 +131,7 @@ class HostData:
132
131
 
133
132
  data = {UPTIME: {}, NETWORK: {}, CPU: {}, DISK: {}, MEMORY: {}, SWAP: {}}
134
133
 
135
- def __init__(self, output: dict, callback: Callable, lm75: LM75) -> None:
134
+ def __init__(self, output: dict, callback: Callable, lm75: LM75Sensor) -> None:
136
135
  """Initialize HostData."""
137
136
  self._hostname = socket.gethostname()
138
137
  self.data[UPTIME] = {HOST: self._hostname, UPTIME: 0}
@@ -1,7 +1,7 @@
1
1
  from typing import Any
2
2
  import os
3
3
  from cerberus import Validator
4
- from ..const import ID, OLED, OUTPUT
4
+ from boneio.const import ID, OLED, OUTPUT
5
5
  from yaml import load, YAMLError, SafeLoader
6
6
 
7
7
 
@@ -0,0 +1,5 @@
1
+ """Input classes."""
2
+
3
+ from boneio.input.gpio import GpioInputButton
4
+
5
+ __all__ = ["GpioInputButton"]
@@ -1,50 +1,28 @@
1
1
  """GPIOInputButton to receive signals."""
2
- import asyncio
3
2
  import logging
4
- import subprocess
5
3
  from datetime import datetime
6
4
  from functools import partial
7
- from typing import Callable
8
5
 
9
- from ..const import (
10
- CONFIG_PIN,
6
+ from boneio.const import (
11
7
  DEBOUNCE_DURATION,
12
8
  DELAY_DURATION,
13
9
  DOUBLE,
14
- GPIO,
15
10
  LONG,
16
11
  LONG_PRESS_DURATION,
17
12
  SECOND_DELAY_DURATION,
18
13
  SINGLE,
19
- ClickTypes,
20
14
  )
21
- from ..helper.gpio import edge_detect, read_input, setup_input
15
+ from boneio.helper import edge_detect, GpioBaseClass
22
16
 
23
17
  _LOGGER = logging.getLogger(__name__)
24
18
 
25
19
 
26
- def configure_pin(pin: str) -> None:
27
- pin = f"{pin[0:3]}0{pin[3]}" if len(pin) == 4 else pin
28
- _LOGGER.debug(f"Configuring pin for GPIO {pin}")
29
- subprocess.run(
30
- [CONFIG_PIN, pin, GPIO],
31
- stdout=subprocess.DEVNULL,
32
- stderr=subprocess.STDOUT,
33
- )
34
-
35
-
36
- class GpioInputButton:
20
+ class GpioInputButton(GpioBaseClass):
37
21
  """Represent Gpio input switch."""
38
22
 
39
- def __init__(
40
- self, pin: str, press_callback: Callable[[ClickTypes, str], None], **kwargs
41
- ) -> None:
23
+ def __init__(self, **kwargs) -> None:
42
24
  """Setup GPIO Input Button"""
43
- self._pin = pin
44
- configure_pin(pin)
45
- self._loop = asyncio.get_running_loop()
46
- self._press_callback = press_callback
47
- setup_input(self._pin)
25
+ super().__init__(**kwargs)
48
26
  edge_detect(self._pin, callback=self._handle_press, bounce=25)
49
27
  self._first_press_timestamp = None
50
28
  self._is_long_press = False
@@ -52,7 +30,7 @@ class GpioInputButton:
52
30
  self._second_check = False
53
31
  _LOGGER.debug("Configured listening for input pin %s", self._pin)
54
32
 
55
- def _handle_press(self, pin) -> None:
33
+ def _handle_press(self, pin: str) -> None:
56
34
  """Handle the button press callback"""
57
35
  # Ignore if we are in a long press
58
36
  if self._is_long_press:
@@ -84,11 +62,6 @@ class GpioInputButton:
84
62
  self.check_press_length,
85
63
  )
86
64
 
87
- @property
88
- def is_pressed(self):
89
- """Is button pressed."""
90
- return read_input(self._pin)
91
-
92
65
  def check_press_length(self) -> None:
93
66
  """Check if it's a single, double or long press"""
94
67
  # Check if button is still pressed
@@ -108,7 +81,7 @@ class GpioInputButton:
108
81
  diff = datetime.now() - self._first_press_timestamp
109
82
  if not self._is_long_press and diff > LONG_PRESS_DURATION:
110
83
  self._is_long_press = True
111
- _LOGGER.debug("Long button press, call callback")
84
+ _LOGGER.debug("Long button press on pin %s, call callback", self._pin)
112
85
  self._loop.call_soon_threadsafe(
113
86
  partial(self._press_callback, LONG, self._pin)
114
87
  )
@@ -128,7 +101,8 @@ class GpioInputButton:
128
101
  if self._second_check:
129
102
  if self._second_press_timestamp:
130
103
  _LOGGER.debug(
131
- "Double click event, roznica %s",
104
+ "Double click event on pin %s, roznica %s",
105
+ self._pin,
132
106
  self._second_press_timestamp - self._first_press_timestamp,
133
107
  )
134
108
  self._loop.call_soon_threadsafe(
@@ -136,7 +110,7 @@ class GpioInputButton:
136
110
  )
137
111
 
138
112
  elif self._first_press_timestamp:
139
- _LOGGER.debug("One click event, call callback")
113
+ _LOGGER.debug("One click event on pin %s, call callback", self._pin)
140
114
  self._loop.call_soon_threadsafe(
141
115
  partial(self._press_callback, SINGLE, self._pin)
142
116
  )
@@ -7,7 +7,7 @@ from adafruit_mcp230xx.mcp23017 import MCP23017
7
7
  from board import SCL, SDA
8
8
  from busio import I2C
9
9
 
10
- from .const import (
10
+ from boneio.const import (
11
11
  ACTION,
12
12
  ACTIONS,
13
13
  ADDRESS,
@@ -28,17 +28,26 @@ from .const import (
28
28
  RELAY,
29
29
  STATE,
30
30
  ClickTypes,
31
+ InputTypes,
32
+ SENSOR,
33
+ SHOW_HA,
34
+ BINARY_SENSOR,
35
+ INPUT_SENSOR,
31
36
  )
32
- from .helper import (
37
+ from boneio.helper import (
33
38
  HostData,
34
39
  ha_relay_availibilty_message,
35
40
  ha_sensor_availibilty_message,
36
41
  ha_sensor_temp_availibilty_message,
42
+ ha_binary_sensor_availibilty_message,
37
43
  host_stats,
44
+ GPIOInputException,
45
+ I2CError,
38
46
  )
39
- from .input import GpioInputButton
40
- from .oled import Oled
41
- from .relay import GpioRelay, MCPRelay
47
+ from boneio.input import GpioInputButton
48
+
49
+ from boneio.relay import GpioRelay, MCPRelay
50
+ from boneio.sensor import GpioInputSensor
42
51
 
43
52
  _LOGGER = logging.getLogger(__name__)
44
53
 
@@ -76,38 +85,46 @@ class Manager:
76
85
 
77
86
  def create_lm75_sensor():
78
87
  """Create LM sensor in manager."""
79
- from .sensor.lm75 import LM75
88
+ from .sensor.lm75 import LM75Sensor
80
89
 
81
90
  name = lm75.get(ID)
82
91
  id = name.replace(" ", "")
83
- self._lm75 = LM75(
84
- id=id,
85
- name=name,
86
- i2c=self._i2cbusio,
87
- address=lm75[ADDRESS],
88
- send_message=self.send_message,
89
- topic_prefix=topic_prefix,
90
- )
91
- self.send_ha_autodiscovery(
92
- id=id,
93
- name=name,
94
- ha_type="sensor",
95
- prefix=ha_discovery_prefix,
96
- availibilty_msg_func=ha_sensor_temp_availibilty_message,
97
- )
98
- self._tasks.append(asyncio.create_task(self._lm75.send_state()))
92
+ try:
93
+ self._lm75 = LM75Sensor(
94
+ id=id,
95
+ name=name,
96
+ i2c=self._i2cbusio,
97
+ address=lm75[ADDRESS],
98
+ send_message=self.send_message,
99
+ topic_prefix=topic_prefix,
100
+ )
101
+ self.send_ha_autodiscovery(
102
+ id=id,
103
+ name=name,
104
+ ha_type="sensor",
105
+ prefix=ha_discovery_prefix,
106
+ availibilty_msg_func=ha_sensor_temp_availibilty_message,
107
+ )
108
+ self._tasks.append(asyncio.create_task(self._lm75.send_state()))
109
+ except I2CError as err:
110
+ _LOGGER.error("Can't configure LM75 sensor. %s", err)
111
+ pass
99
112
 
100
113
  def create_mcp23017():
101
114
  """Create MCP23017."""
102
115
  for mcp in mcp23017:
103
116
  id = mcp[ID] or mcp[ADDRESS]
104
- self._mcp[id] = MCP23017(i2c=self._i2cbusio, address=mcp[ADDRESS])
105
- sleep_time = mcp.get(INIT_SLEEP, 0)
106
- _LOGGER.debug(
107
- f"Sleeping for {sleep_time}s while MCP {id} is initializing."
108
- )
109
- time.sleep(sleep_time)
110
- self._grouped_outputs[id] = {}
117
+ try:
118
+ self._mcp[id] = MCP23017(i2c=self._i2cbusio, address=mcp[ADDRESS])
119
+ sleep_time = mcp.get(INIT_SLEEP, 0)
120
+ _LOGGER.debug(
121
+ f"Sleeping for {sleep_time}s while MCP {id} is initializing."
122
+ )
123
+ time.sleep(sleep_time)
124
+ self._grouped_outputs[id] = {}
125
+ except TimeoutError as err:
126
+ _LOGGER.error("Can't connect to MCP %s. %s", id, err)
127
+ pass
111
128
 
112
129
  if lm75:
113
130
  create_lm75_sensor()
@@ -167,25 +184,60 @@ class Manager:
167
184
  out.send_state,
168
185
  )
169
186
 
170
- def configure_button(gpio):
171
- pin = gpio[PIN]
172
- button = GpioInputButton(
173
- pin=pin,
174
- press_callback=lambda x, i: self.press_callback(x, i, gpio[ACTIONS]),
175
- rest_pin=gpio,
176
- )
177
- self.send_ha_autodiscovery(
178
- id=pin,
179
- name=gpio.get(ID, pin),
180
- ha_type="sensor",
181
- prefix=ha_discovery_prefix,
182
- availibilty_msg_func=ha_sensor_availibilty_message,
183
- )
184
- return button
187
+ def configure_input(gpio):
188
+ try:
189
+ pin = gpio[PIN]
190
+ input_type = gpio.get(KIND)
191
+ if input_type == SENSOR:
192
+ GpioInputSensor(
193
+ pin=pin,
194
+ press_callback=lambda x, i: self.press_callback(
195
+ x=x,
196
+ inpin=i,
197
+ actions=gpio.get(ACTIONS, {}),
198
+ input_type=INPUT_SENSOR,
199
+ ),
200
+ rest_pin=gpio,
201
+ )
202
+ availibilty_msg_func = ha_binary_sensor_availibilty_message
203
+ ha_type = BINARY_SENSOR
204
+ else:
205
+ GpioInputButton(
206
+ pin=pin,
207
+ press_callback=lambda x, i: self.press_callback(
208
+ x=x,
209
+ inpin=i,
210
+ actions=gpio.get(ACTIONS, {}),
211
+ input_type=INPUT,
212
+ ),
213
+ rest_pin=gpio,
214
+ )
215
+ availibilty_msg_func = ha_sensor_availibilty_message
216
+ ha_type = SENSOR
217
+ if gpio.get(SHOW_HA, True):
218
+ print(
219
+ "INPUT sending disco",
220
+ ha_type,
221
+ ha_discovery_prefix,
222
+ availibilty_msg_func,
223
+ )
224
+ self.send_ha_autodiscovery(
225
+ id=pin,
226
+ name=gpio.get(ID, pin),
227
+ ha_type=ha_type,
228
+ prefix=ha_discovery_prefix,
229
+ availibilty_msg_func=availibilty_msg_func,
230
+ )
231
+ except GPIOInputException as err:
232
+ _LOGGER.error("This PIN %s can't be configured. %s", pin, err)
233
+ pass
185
234
 
186
- self.buttons = [configure_button(gpio=gpio) for gpio in self._input_pins]
235
+ for gpio in self._input_pins:
236
+ configure_input(gpio=gpio)
187
237
 
188
238
  if oled:
239
+ from boneio.oled import Oled
240
+
189
241
  self._host_data = HostData(
190
242
  output=self._grouped_outputs,
191
243
  lm75=self._lm75,
@@ -194,9 +246,12 @@ class Manager:
194
246
  for f in host_stats.values():
195
247
  self._tasks.append(asyncio.create_task(f(self._host_data)))
196
248
  _LOGGER.debug("Gathering host data enabled.")
197
- self._oled = Oled(
198
- host_data=self._host_data, output_groups=list(self._grouped_outputs)
199
- )
249
+ try:
250
+ self._oled = Oled(
251
+ host_data=self._host_data, output_groups=list(self._grouped_outputs)
252
+ )
253
+ except GPIOInputException as err:
254
+ _LOGGER.error("Can't configure OLED display. %s", err)
200
255
 
201
256
  self.send_message(topic=f"{topic_prefix}/{STATE}", payload=ONLINE)
202
257
  _LOGGER.info("BoneIO manager is ready.")
@@ -208,18 +263,20 @@ class Manager:
208
263
  def get_tasks(self) -> Set[asyncio.Task]:
209
264
  return self._tasks
210
265
 
211
- def press_callback(self, x: ClickTypes, inpin: str, actions: dict) -> None:
266
+ def press_callback(
267
+ self, x: ClickTypes, inpin: str, actions: dict, input_type: InputTypes = INPUT
268
+ ) -> None:
212
269
  """Press callback to use in input gpio.
213
270
  If relay input map is provided also toggle action on relay."""
214
- topic = f"{self._topic_prefix}/{INPUT}/{inpin}"
271
+ topic = f"{self._topic_prefix}/{input_type}/{inpin}"
215
272
  self.send_message(topic=topic, payload=x)
216
273
  action = actions.get(x)
217
274
  if action:
218
275
  if action[ACTION] == OUTPUT:
219
276
  """For now only output type is supported"""
220
- output_gpio = self.output.get(action[PIN])
221
- if output_gpio:
222
- output_gpio.toggle()
277
+ relay = self.output.get(action[PIN].replace(" ", ""))
278
+ if relay:
279
+ relay.toggle()
223
280
  # This is similar how Z2M is clearing click sensor.
224
281
  # self._loop.call_later(1, self.send_message, topic, "")
225
282
 
@@ -12,7 +12,7 @@ from asyncio_mqtt import MqttError
12
12
  from paho.mqtt.properties import Properties
13
13
  from paho.mqtt.subscribeoptions import SubscribeOptions
14
14
 
15
- from .const import PAHO
15
+ from boneio.const import PAHO
16
16
 
17
17
  _LOGGER = logging.getLogger(__name__)
18
18
 
@@ -7,9 +7,8 @@ from luma.core.render import canvas
7
7
  from luma.oled.device import sh1106
8
8
  from PIL import ImageDraw
9
9
 
10
- from .const import CPU, DISK, MEMORY, NETWORK, OLED_PIN, SWAP, UPTIME, WHITE
11
- from .helper import HostData, edge_detect, make_font, setup_input
12
- from .input import configure_pin
10
+ from boneio.const import CPU, DISK, MEMORY, NETWORK, OLED_PIN, SWAP, UPTIME, WHITE
11
+ from boneio.helper import HostData, configure_pin, edge_detect, make_font, setup_input
13
12
 
14
13
  _LOGGER = logging.getLogger(__name__)
15
14
 
@@ -38,7 +37,7 @@ class Oled:
38
37
  self._host_data = host_data
39
38
  configure_pin(OLED_PIN)
40
39
  setup_input(OLED_PIN)
41
- edge_detect(OLED_PIN, callback=self._handle_press, bounce=50)
40
+ edge_detect(pin=OLED_PIN, callback=self._handle_press, bounce=50)
42
41
  serial = i2c(port=2, address=0x3C)
43
42
  self._device = sh1106(serial)
44
43
  _LOGGER.debug("Configuring OLED screen.")
@@ -0,0 +1,5 @@
1
+ """Relay module."""
2
+ from boneio.relay.gpio import GpioRelay
3
+ from boneio.relay.mcp import MCPRelay
4
+
5
+ __all__ = ["MCPRelay", "GpioRelay"]
@@ -4,7 +4,7 @@ import asyncio
4
4
  import logging
5
5
  from typing import Callable, Union
6
6
 
7
- from ..const import OFF, ON, RELAY, STATE, SWITCH
7
+ from boneio.const import OFF, ON, RELAY, STATE, SWITCH
8
8
 
9
9
  _LOGGER = logging.getLogger(__name__)
10
10
 
@@ -5,8 +5,9 @@ Created just in case.
5
5
 
6
6
  import logging
7
7
 
8
- from ..helper.gpio import HIGH, LOW, read_input, setup_output, write_output
9
- from .basic import BasicRelay
8
+ from boneio.helper import read_input, setup_output, write_output
9
+ from boneio.relay.basic import BasicRelay
10
+ from boneio.const import HIGH, LOW
10
11
 
11
12
  _LOGGER = logging.getLogger(__name__)
12
13
 
@@ -4,7 +4,7 @@ import logging
4
4
 
5
5
  from adafruit_mcp230xx.mcp23017 import MCP23017
6
6
 
7
- from .basic import BasicRelay
7
+ from boneio.relay.basic import BasicRelay
8
8
 
9
9
  _LOGGER = logging.getLogger(__name__)
10
10
 
@@ -131,7 +131,7 @@ output:
131
131
  label: If HA discovery is used device if relay is light or switch.
132
132
 
133
133
 
134
- gpio_input:
134
+ input:
135
135
  type: list
136
136
  meta:
137
137
  label: GPIO inputs section
@@ -148,6 +148,19 @@ gpio_input:
148
148
  required: True
149
149
  meta:
150
150
  label: PIN to use.
151
+ show_in_ha:
152
+ type: boolean
153
+ required: True
154
+ default: True
155
+ meta:
156
+ label: If you want you can disable discovering this input in HA.
157
+ kind:
158
+ type: string
159
+ allowed: ['switch', 'sensor']
160
+ default: switch
161
+ required: True
162
+ meta:
163
+ label: Either switch or sensor. If sensor then no clicks are detected, just simple on/off on gpio.
151
164
  actions:
152
165
  required: False
153
166
  type: dict
@@ -188,3 +201,27 @@ gpio_input:
188
201
  type: string
189
202
  message:
190
203
  type: string
204
+ pressed:
205
+ required: False
206
+ type: dict
207
+ schema:
208
+ action:
209
+ type: string
210
+ allowed: ['mqtt', 'output']
211
+ default: output
212
+ pin:
213
+ type: string
214
+ message:
215
+ type: string
216
+ released:
217
+ required: False
218
+ type: dict
219
+ schema:
220
+ action:
221
+ type: string
222
+ allowed: ['mqtt', 'output']
223
+ default: output
224
+ pin:
225
+ type: string
226
+ message:
227
+ type: string
@@ -0,0 +1,5 @@
1
+ """Sensor module."""
2
+ from boneio.sensor.lm75 import LM75Sensor
3
+ from boneio.sensor.gpio import GpioInputSensor
4
+
5
+ __all__ = ["LM75Sensor", "GpioInputSensor"]
@@ -0,0 +1,32 @@
1
+ """GPIOInputButton to receive signals."""
2
+ import logging
3
+ from functools import partial
4
+
5
+ from boneio.const import BOTH, PRESSED, RELEASED
6
+ from boneio.helper import edge_detect, GpioBaseClass
7
+
8
+ _LOGGER = logging.getLogger(__name__)
9
+
10
+
11
+ class GpioInputSensor(GpioBaseClass):
12
+ """Represent Gpio sensor on input boards."""
13
+
14
+ def __init__(self, **kwargs) -> None:
15
+ """Setup GPIO Input Button"""
16
+ super().__init__(**kwargs)
17
+ edge_detect(self._pin, callback=self._handle_press, bounce=25, edge=BOTH)
18
+ _LOGGER.debug("Configured sensor pin %s", self._pin)
19
+
20
+ def _handle_press(self, pin: str) -> None:
21
+ """Handle the button press callback"""
22
+ # Ignore if we are in a long press
23
+ if self.is_pressed:
24
+ _LOGGER.debug("Pressed event on pin %s", self._pin)
25
+ self._loop.call_soon_threadsafe(
26
+ partial(self._press_callback, PRESSED, self._pin)
27
+ )
28
+ else:
29
+ _LOGGER.debug("Released event on pin %s", self._pin)
30
+ self._loop.call_soon_threadsafe(
31
+ partial(self._press_callback, RELEASED, self._pin)
32
+ )
@@ -3,10 +3,12 @@
3
3
  import asyncio
4
4
  from adafruit_pct2075 import PCT2075
5
5
  from typing import Callable, Union
6
- from ..const import STATE, SENSOR
6
+ from boneio.const import STATE, SENSOR, LM75
7
7
 
8
+ from boneio.helper.exceptions import I2CError
8
9
 
9
- class LM75:
10
+
11
+ class LM75Sensor:
10
12
  """Represent LM75 sensor in BoneIO."""
11
13
 
12
14
  def __init__(
@@ -16,14 +18,17 @@ class LM75:
16
18
  topic_prefix: str,
17
19
  name: str,
18
20
  send_message: Callable[[str, Union[str, dict]], None],
19
- id: str = "lm75",
21
+ id: str = LM75,
20
22
  ):
21
23
  """Initialize LM75 class."""
22
24
  self._id = id
23
25
  self._name = name
24
26
  self._send_message = send_message
25
27
  self._send_topic = f"{topic_prefix}/{SENSOR}/{self._id}"
26
- self._pct = PCT2075(i2c_bus=i2c, address=address)
28
+ try:
29
+ self._pct = PCT2075(i2c_bus=i2c, address=address)
30
+ except ValueError as err:
31
+ raise I2CError(err)
27
32
 
28
33
  @property
29
34
  def name(self):
@@ -0,0 +1,2 @@
1
+ # flake8: noqa
2
+ __version__ = "0.1.0.dev15"
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: boneio
3
- Version: 0.1.0.dev13
3
+ Version: 0.1.0.dev15
4
4
  Summary: Python Helper for BoneIO
5
5
  Home-page: https://github.com/maciejk1984/boneIO
6
6
  License: GNU General Public License v3.0
7
- Download-URL: https://github.com/maciejk1984/boneIO/archive/0.1.0.dev13.zip
7
+ Download-URL: https://github.com/maciejk1984/boneIO/archive/0.1.0.dev15.zip
8
8
  Platform: UNKNOWN
9
9
  Classifier: Programming Language :: Python
10
10
  Classifier: Programming Language :: Python :: 3.7
@@ -18,6 +18,7 @@ boneio.egg-info/requires.txt
18
18
  boneio.egg-info/top_level.txt
19
19
  boneio/fonts/danube__.ttf
20
20
  boneio/helper/__init__.py
21
+ boneio/helper/exceptions.py
21
22
  boneio/helper/gpio.py
22
23
  boneio/helper/ha_discovery.py
23
24
  boneio/helper/oled.py
@@ -30,4 +31,5 @@ boneio/relay/basic.py
30
31
  boneio/relay/gpio.py
31
32
  boneio/relay/mcp.py
32
33
  boneio/sensor/__init__.py
34
+ boneio/sensor/gpio.py
33
35
  boneio/sensor/lm75.py
@@ -1,23 +0,0 @@
1
- """Helper dir for BoneIO."""
2
- from .gpio import edge_detect, setup_input
3
- from .oled import make_font
4
- from .stats import HostData, host_stats
5
- from .yaml import CustomValidator, load_yaml_file
6
- from .ha_discovery import (
7
- ha_relay_availibilty_message,
8
- ha_sensor_availibilty_message,
9
- ha_sensor_temp_availibilty_message,
10
- )
11
-
12
- __all__ = [
13
- "CustomValidator",
14
- "load_yaml_file",
15
- "HostData",
16
- "host_stats",
17
- "setup_input",
18
- "edge_detect",
19
- "make_font",
20
- "ha_relay_availibilty_message",
21
- "ha_sensor_availibilty_message",
22
- "ha_sensor_temp_availibilty_message",
23
- ]
@@ -1,30 +0,0 @@
1
- from Adafruit_BBIO import GPIO
2
- from Adafruit_BBIO.GPIO import HIGH, LOW
3
-
4
-
5
- def setup_output(pin: str):
6
- """Set up a GPIO as output."""
7
-
8
- GPIO.setup(pin, GPIO.OUT, pull_up_down=GPIO.PUD_DOWN)
9
-
10
-
11
- def setup_input(pin: str, pull_mode: str = "UP"):
12
- """Set up a GPIO as input."""
13
- GPIO.setup(pin, GPIO.IN, GPIO.PUD_DOWN if pull_mode == "DOWN" else GPIO.PUD_UP)
14
-
15
-
16
- def write_output(pin: str, value: str):
17
- """Write a value to a GPIO."""
18
-
19
- GPIO.output(pin, value)
20
-
21
-
22
- def read_input(pin: str, on_state=LOW):
23
- """Read a value from a GPIO."""
24
- return GPIO.input(pin) is on_state
25
-
26
-
27
- def edge_detect(pin, callback, bounce):
28
- """Add detection for RISING and FALLING events."""
29
-
30
- GPIO.add_event_detect(pin, GPIO.FALLING, callback=callback, bouncetime=bounce)
@@ -1,5 +0,0 @@
1
- """Input classes."""
2
-
3
- from .gpio import GpioInputButton, configure_pin
4
-
5
- __all__ = ["GpioInputButton", "configure_pin"]
@@ -1,5 +0,0 @@
1
- """Relay module."""
2
- from .gpio import GpioRelay
3
- from .mcp import MCPRelay
4
-
5
- __all__ = ["MCPRelay", "GpioRelay"]
@@ -1,4 +0,0 @@
1
- """Sensor module."""
2
- from .lm75 import LM75
3
-
4
- __all__ = ["LM75"]
@@ -1,2 +0,0 @@
1
- # flake8: noqa
2
- __version__ = "0.1.0.dev13"
File without changes
File without changes
File without changes
File without changes