Skip to content

Commit

Permalink
Ensure slot order
Browse files Browse the repository at this point in the history
  • Loading branch information
DeerMaximum committed Jan 17, 2024
1 parent 0cd2700 commit a93a91d
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 23 deletions.
6 changes: 6 additions & 0 deletions custom_components/ta_coe/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
CONF_ENTITIES_TO_SEND,
DIGITAL_DOMAINS,
DOMAIN,
FREE_SLOT_MARKER_ANALOGE,
FREE_SLOT_MARKER_DIGITAL,
TYPE_BINARY,
)

Expand Down Expand Up @@ -103,11 +105,15 @@ def extra_state_attributes(self) -> dict[str, Any]:
if x.split(".")[0] in DIGITAL_DOMAINS:
digital[index] = x
index += 1
elif x == FREE_SLOT_MARKER_DIGITAL:
index += 1

index = 1
for x in self._entity.values():
if x.split(".")[0] in ANALOG_DOMAINS:
analog[index] = x
index += 1
elif x == FREE_SLOT_MARKER_ANALOGE:
index += 1

return {ATTR_ANALOG_ORDER: analog, ATTR_DIGITAL_ORDER: digital}
44 changes: 32 additions & 12 deletions custom_components/ta_coe/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
CONF_ENTITIES_TO_SEND,
CONF_SCAN_INTERVAL,
CONF_SLOT_COUNT,
DIGITAL_DOMAINS,
DOMAIN,
FREE_SLOT_MARKER,
FREE_SLOT_MARKER_ANALOGE,
FREE_SLOT_MARKER_DIGITAL,
FREE_SLOT_MARKERS,
SCAN_INTERVAL,
)

Expand Down Expand Up @@ -227,11 +230,16 @@ async def async_step_init(
],
)

def get_new_slot_index(self) -> tuple[int, bool]:
def get_new_slot_index(self, is_digital: bool) -> tuple[int, bool]:
"""Get the first index of an empty slot."""
if FREE_SLOT_MARKER in self.data[CONF_ENTITIES_TO_SEND].values():
index = list(self.data[CONF_ENTITIES_TO_SEND]).keys()[
list(self.data[CONF_ENTITIES_TO_SEND].values()).index(FREE_SLOT_MARKER)
search_marker = FREE_SLOT_MARKER_ANALOGE

if is_digital:
search_marker = FREE_SLOT_MARKER_DIGITAL

if search_marker in self.data[CONF_ENTITIES_TO_SEND].values():
index = list(self.data[CONF_ENTITIES_TO_SEND].keys())[
list(self.data[CONF_ENTITIES_TO_SEND].values()).index(search_marker)
]
return index, False
else:
Expand All @@ -252,11 +260,12 @@ async def async_step_add_send_values(
self.data[CONF_ENTITIES_TO_SEND] = {}

if new_id not in self.data[CONF_ENTITIES_TO_SEND].values():
index, used_slot = self.get_new_slot_index()
is_digital = new_id.split(".")[0] in DIGITAL_DOMAINS
index, new_slot = self.get_new_slot_index(is_digital)

self.data[CONF_ENTITIES_TO_SEND][str(index)] = new_id

if not used_slot:
if new_slot:
self.data[CONF_SLOT_COUNT] = index + 1

return self.async_create_entry(title="", data=self.data)
Expand All @@ -280,9 +289,13 @@ async def async_step_change_send_values(
old_id = user_input["old_value"]

if (
old_id in self.data[CONF_ENTITIES_TO_SEND].values()
or new_id not in self.data[CONF_ENTITIES_TO_SEND].values()
) and old_id is not FREE_SLOT_MARKER:
(
old_id in self.data[CONF_ENTITIES_TO_SEND].values()
or new_id not in self.data[CONF_ENTITIES_TO_SEND].values()
)
and old_id not in FREE_SLOT_MARKERS
and new_id not in FREE_SLOT_MARKERS
):
index = [
k
for k, v in self.data[CONF_ENTITIES_TO_SEND].items()
Expand Down Expand Up @@ -312,14 +325,21 @@ async def async_step_delete_send_values(self, user_input=None):

if user_input is not None:
for index in user_input[CONF_ENTITIES_TO_SEND]:
self.data[CONF_ENTITIES_TO_SEND][index] = FREE_SLOT_MARKER
marker = FREE_SLOT_MARKER_ANALOGE
if (
self.data[CONF_ENTITIES_TO_SEND][index].split(".")[0]
in DIGITAL_DOMAINS
):
marker = FREE_SLOT_MARKER_DIGITAL

self.data[CONF_ENTITIES_TO_SEND][index] = marker

return self.async_create_entry(title="", data=self.data)

entities_without_marker = {
key: value
for key, value in self.data.get(CONF_ENTITIES_TO_SEND, {}).items()
if value != FREE_SLOT_MARKER
if value not in FREE_SLOT_MARKERS
}

return self.async_show_form(
Expand Down
4 changes: 3 additions & 1 deletion custom_components/ta_coe/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
CONF_ENTITIES_TO_SEND = "entities_to_send"
CONF_SLOT_COUNT = "slot_count"

FREE_SLOT_MARKER = "--FREE_SLOT_MARKER--"
FREE_SLOT_MARKER_ANALOGE = "--FREE_SLOT_MARKER_A--"
FREE_SLOT_MARKER_DIGITAL = "--FREE_SLOT_MARKER_D--"
FREE_SLOT_MARKERS = [FREE_SLOT_MARKER_ANALOGE, FREE_SLOT_MARKER_DIGITAL]

ALLOWED_DOMAINS = ("sensor", "binary_sensor", "number", "input_boolean")

Expand Down
5 changes: 3 additions & 2 deletions custom_components/ta_coe/state_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
_LOGGER,
ANALOG_DOMAINS,
DIGITAL_DOMAINS,
FREE_SLOT_MARKER,
FREE_SLOT_MARKERS,
TYPE_BINARY,
TYPE_SENSOR,
)
Expand Down Expand Up @@ -57,7 +57,7 @@ async def get_all_states(self) -> None:
_LOGGER.debug("Update all states")

for entity_id in self._entity_list:
if entity_id == FREE_SLOT_MARKER:
if entity_id in FREE_SLOT_MARKERS:
continue

state = self._hass.states.get(entity_id)
Expand Down Expand Up @@ -91,6 +91,7 @@ async def _update_listener(self, event: Event) -> None:
new_state is None
or not self._is_state_valid(new_state.state)
or not self._has_state_changed(new_state)
or new_state.entity_id in FREE_SLOT_MARKERS
):
return

Expand Down
14 changes: 10 additions & 4 deletions tests/test_state_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
from custom_components.ta_coe.const import (
ANALOG_DOMAINS,
DIGITAL_DOMAINS,
FREE_SLOT_MARKER,
FREE_SLOT_MARKER_ANALOGE,
FREE_SLOT_MARKER_DIGITAL,
FREE_SLOT_MARKERS,
)
from custom_components.ta_coe.state_sender import StateSender
from tests import (
Expand Down Expand Up @@ -56,7 +58,11 @@ async def test_observer_receive_all_states_all_states(hass: HomeAssistant):
@pytest.mark.asyncio
async def test_observer_receive_all_states_ignore_free_slot(hass: HomeAssistant):
"""Test if the observer ignores the free slot maker on get all states."""
entity_list = {"0": FREE_SLOT_MARKER, "1": "binary_sensor.test"}
entity_list = {
"0": FREE_SLOT_MARKER_ANALOGE,
"1": "binary_sensor.test",
"2": FREE_SLOT_MARKER_DIGITAL,
}

with patch(STATE_AVAILABLE_PACKAGE) as get_states_mock, patch(
STATE_SENDER_UPDATE
Expand All @@ -67,10 +73,10 @@ async def test_observer_receive_all_states_ignore_free_slot(hass: HomeAssistant)
):
await StateObserver(hass, coe, state_sender, entity_list).get_all_states()

assert len(get_states_mock.call_args_list) == len(entity_list) - 1
assert len(get_states_mock.call_args_list) == len(entity_list) - 2

for called_id in get_states_mock.call_args_list:
assert called_id.args[0] != FREE_SLOT_MARKER
assert called_id.args[0] not in FREE_SLOT_MARKERS


@pytest.mark.asyncio
Expand Down
8 changes: 4 additions & 4 deletions tests/test_state_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
ATTR_ANALOG_ORDER,
ATTR_DIGITAL_ORDER,
CONF_CAN_IDS,
FREE_SLOT_MARKER_ANALOGE,
FREE_SLOT_MARKER_DIGITAL,
)
from tests import (
COE_SEND_ANALOG_VALUES_PACKAGE,
Expand All @@ -27,8 +29,8 @@
CONF_HOST: "http://192.168.2.101",
CONF_CAN_IDS: [1, 20],
CONF_ENTITIES_TO_SEND: {
1: "sensor.coe_analog_1",
2: "binary_sensor.coe_digital_1",
1: FREE_SLOT_MARKER_ANALOGE,
2: FREE_SLOT_MARKER_DIGITAL,
3: "sensor.coe_analog_2",
4: "binary_sensor.coe_digital_2",
},
Expand Down Expand Up @@ -103,11 +105,9 @@ async def test_state_sensor_on(hass: HomeAssistant) -> None:
assert state_a1.state == STATE_ON
assert state_a1.attributes.get("friendly_name") == "CoE: Send value state"
assert state_a1.attributes.get(ATTR_ANALOG_ORDER) == {
1: ENTRY_DATA[CONF_ENTITIES_TO_SEND][1],
2: ENTRY_DATA[CONF_ENTITIES_TO_SEND][3],
}
assert state_a1.attributes.get(ATTR_DIGITAL_ORDER) == {
1: ENTRY_DATA[CONF_ENTITIES_TO_SEND][2],
2: ENTRY_DATA[CONF_ENTITIES_TO_SEND][4],
}

Expand Down

0 comments on commit a93a91d

Please sign in to comment.