Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/tasmota/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Tasmota (beta)",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/tasmota",
"requirements": ["hatasmota==0.0.27"],
"requirements": ["hatasmota==0.0.29"],
"dependencies": ["mqtt"],
"mqtt": ["tasmota/discovery/#"],
"codeowners": ["@emontnemery"]
Expand Down
3 changes: 1 addition & 2 deletions homeassistant/components/tasmota/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ async def async_added_to_hass(self) -> None:
@callback
def availability_updated(self, available: bool) -> None:
"""Handle updated availability."""
if available and not self._available:
self._tasmota_entity.poll_status()
self._tasmota_entity.poll_status()
self._available = available
self.async_write_ha_state()

Expand Down
81 changes: 76 additions & 5 deletions homeassistant/components/tasmota/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@

from hatasmota import status_sensor
from hatasmota.const import (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol at all these renames. You can also do from hatasmota import const as hc

CONCENTRATION_MICROGRAMS_PER_CUBIC_METER as TASMOTA_CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION as TASMOTA_CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION as TASMOTA_CONCENTRATION_PARTS_PER_MILLION,
ELECTRICAL_CURRENT_AMPERE as TASMOTA_ELECTRICAL_CURRENT_AMPERE,
ELECTRICAL_VOLT_AMPERE as TASMOTA_ELECTRICAL_VOLT_AMPERE,
ENERGY_KILO_WATT_HOUR as TASMOTA_ENERGY_KILO_WATT_HOUR,
FREQUENCY_HERTZ as TASMOTA_FREQUENCY_HERTZ,
LENGTH_CENTIMETERS as TASMOTA_LENGTH_CENTIMETERS,
LIGHT_LUX as TASMOTA_LIGHT_LUX,
MASS_KILOGRAMS as TASMOTA_MASS_KILOGRAMS,
PERCENTAGE as TASMOTA_PERCENTAGE,
POWER_WATT as TASMOTA_POWER_WATT,
PRESSURE_HPA as TASMOTA_PRESSURE_HPA,
SENSOR_AMBIENT,
SENSOR_APPARENT_POWERUSAGE,
SENSOR_BATTERY,
Expand Down Expand Up @@ -35,12 +48,13 @@
SENSOR_PROXIMITY,
SENSOR_REACTIVE_POWERUSAGE,
SENSOR_STATUS_IP,
SENSOR_STATUS_LAST_RESTART_TIME,
SENSOR_STATUS_LINK_COUNT,
SENSOR_STATUS_MQTT_COUNT,
SENSOR_STATUS_RESTART,
SENSOR_STATUS_RESTART_REASON,
SENSOR_STATUS_RSSI,
SENSOR_STATUS_SIGNAL,
SENSOR_STATUS_UPTIME,
SENSOR_STATUS_SSID,
SENSOR_TEMPERATURE,
SENSOR_TODAY,
SENSOR_TOTAL,
Expand All @@ -49,17 +63,47 @@
SENSOR_VOLTAGE,
SENSOR_WEIGHT,
SENSOR_YESTERDAY,
SIGNAL_STRENGTH_DECIBELS as TASMOTA_SIGNAL_STRENGTH_DECIBELS,
SPEED_KILOMETERS_PER_HOUR as TASMOTA_SPEED_KILOMETERS_PER_HOUR,
SPEED_METERS_PER_SECOND as TASMOTA_SPEED_METERS_PER_SECOND,
SPEED_MILES_PER_HOUR as TASMOTA_SPEED_MILES_PER_HOUR,
TEMP_CELSIUS as TASMOTA_TEMP_CELSIUS,
TEMP_FAHRENHEIT as TASMOTA_TEMP_FAHRENHEIT,
TEMP_KELVIN as TASMOTA_TEMP_KELVIN,
VOLT as TASMOTA_VOLT,
)

from homeassistant.components import sensor
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_ILLUMINANCE,
DEVICE_CLASS_POWER,
DEVICE_CLASS_PRESSURE,
DEVICE_CLASS_SIGNAL_STRENGTH,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_TIMESTAMP,
ELECTRICAL_CURRENT_AMPERE,
ELECTRICAL_VOLT_AMPERE,
ENERGY_KILO_WATT_HOUR,
FREQUENCY_HERTZ,
LENGTH_CENTIMETERS,
LIGHT_LUX,
MASS_KILOGRAMS,
PERCENTAGE,
POWER_WATT,
PRESSURE_HPA,
SIGNAL_STRENGTH_DECIBELS,
SPEED_KILOMETERS_PER_HOUR,
SPEED_METERS_PER_SECOND,
SPEED_MILES_PER_HOUR,
TEMP_CELSIUS,
TEMP_FAHRENHEIT,
TEMP_KELVIN,
VOLT,
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
Expand Down Expand Up @@ -108,10 +152,11 @@
SENSOR_PRESSUREATSEALEVEL: {DEVICE_CLASS: DEVICE_CLASS_PRESSURE},
SENSOR_PROXIMITY: {ICON: "mdi:ruler"},
SENSOR_REACTIVE_POWERUSAGE: {DEVICE_CLASS: DEVICE_CLASS_POWER},
SENSOR_STATUS_RESTART: {ICON: "mdi:information-outline"},
SENSOR_STATUS_LAST_RESTART_TIME: {DEVICE_CLASS: DEVICE_CLASS_TIMESTAMP},
SENSOR_STATUS_RESTART_REASON: {ICON: "mdi:information-outline"},
SENSOR_STATUS_SIGNAL: {DEVICE_CLASS: DEVICE_CLASS_SIGNAL_STRENGTH},
SENSOR_STATUS_RSSI: {ICON: "mdi:access-point"},
SENSOR_STATUS_UPTIME: {ICON: "mdi:progress-clock"},
SENSOR_STATUS_SSID: {ICON: "mdi:access-point-network"},
SENSOR_TEMPERATURE: {DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE},
SENSOR_TODAY: {DEVICE_CLASS: DEVICE_CLASS_POWER},
SENSOR_TOTAL: {DEVICE_CLASS: DEVICE_CLASS_POWER},
Expand All @@ -122,6 +167,30 @@
SENSOR_YESTERDAY: {DEVICE_CLASS: DEVICE_CLASS_POWER},
}

SENSOR_UNIT_MAP = {
TASMOTA_CONCENTRATION_MICROGRAMS_PER_CUBIC_METER: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
TASMOTA_CONCENTRATION_PARTS_PER_BILLION: CONCENTRATION_PARTS_PER_BILLION,
TASMOTA_CONCENTRATION_PARTS_PER_MILLION: CONCENTRATION_PARTS_PER_MILLION,
TASMOTA_ELECTRICAL_CURRENT_AMPERE: ELECTRICAL_CURRENT_AMPERE,
TASMOTA_ELECTRICAL_VOLT_AMPERE: ELECTRICAL_VOLT_AMPERE,
TASMOTA_ENERGY_KILO_WATT_HOUR: ENERGY_KILO_WATT_HOUR,
TASMOTA_FREQUENCY_HERTZ: FREQUENCY_HERTZ,
TASMOTA_LENGTH_CENTIMETERS: LENGTH_CENTIMETERS,
TASMOTA_LIGHT_LUX: LIGHT_LUX,
TASMOTA_MASS_KILOGRAMS: MASS_KILOGRAMS,
TASMOTA_PERCENTAGE: PERCENTAGE,
TASMOTA_POWER_WATT: POWER_WATT,
TASMOTA_PRESSURE_HPA: PRESSURE_HPA,
TASMOTA_SIGNAL_STRENGTH_DECIBELS: SIGNAL_STRENGTH_DECIBELS,
TASMOTA_SPEED_KILOMETERS_PER_HOUR: SPEED_KILOMETERS_PER_HOUR,
TASMOTA_SPEED_METERS_PER_SECOND: SPEED_METERS_PER_SECOND,
TASMOTA_SPEED_MILES_PER_HOUR: SPEED_MILES_PER_HOUR,
TASMOTA_TEMP_CELSIUS: TEMP_CELSIUS,
TASMOTA_TEMP_FAHRENHEIT: TEMP_FAHRENHEIT,
TASMOTA_TEMP_KELVIN: TEMP_KELVIN,
TASMOTA_VOLT: VOLT,
}


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up Tasmota sensor dynamically through discovery."""
Expand Down Expand Up @@ -190,9 +259,11 @@ def icon(self):
@property
def state(self):
"""Return the state of the entity."""
if self._state and self.device_class == DEVICE_CLASS_TIMESTAMP:
return self._state.isoformat()
return self._state

@property
def unit_of_measurement(self):
"""Return the unit this state is expressed in."""
return self._tasmota_entity.unit
return SENSOR_UNIT_MAP.get(self._tasmota_entity.unit, self._tasmota_entity.unit)
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ hass-nabucasa==0.37.1
hass_splunk==0.1.1

# homeassistant.components.tasmota
hatasmota==0.0.27
hatasmota==0.0.29

# homeassistant.components.jewish_calendar
hdate==0.9.12
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ hangups==0.4.11
hass-nabucasa==0.37.1

# homeassistant.components.tasmota
hatasmota==0.0.27
hatasmota==0.0.29

# homeassistant.components.jewish_calendar
hdate==0.9.12
Expand Down
48 changes: 48 additions & 0 deletions tests/components/tasmota/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,54 @@ async def test_controlling_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
assert state.state == STATE_OFF


async def test_pushon_controlling_state_via_mqtt(hass, mqtt_mock, setup_tasmota):
"""Test state update via MQTT."""
config = copy.deepcopy(DEFAULT_CONFIG)
config["swc"][0] = 13
mac = config["mac"]

async_fire_mqtt_message(
hass,
f"{DEFAULT_PREFIX}/{mac}/config",
json.dumps(config),
)
await hass.async_block_till_done()

state = hass.states.get("binary_sensor.test")
assert state.state == "unavailable"
assert not state.attributes.get(ATTR_ASSUMED_STATE)

async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/LWT", "Online")
state = hass.states.get("binary_sensor.test")
assert state.state == STATE_OFF
assert not state.attributes.get(ATTR_ASSUMED_STATE)

# Test normal state update
async_fire_mqtt_message(
hass, "tasmota_49A3BC/stat/RESULT", '{"Switch1":{"Action":"ON"}}'
)
state = hass.states.get("binary_sensor.test")
assert state.state == STATE_ON

async_fire_mqtt_message(
hass, "tasmota_49A3BC/stat/RESULT", '{"Switch1":{"Action":"OFF"}}'
)
state = hass.states.get("binary_sensor.test")
assert state.state == STATE_OFF

# Test periodic state update is ignored
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/SENSOR", '{"Switch1":"ON"}')
state = hass.states.get("binary_sensor.test")
assert state.state == STATE_OFF

# Test polled state update is ignored
async_fire_mqtt_message(
hass, "tasmota_49A3BC/stat/STATUS10", '{"StatusSNS":{"Switch1":"ON"}}'
)
state = hass.states.get("binary_sensor.test")
assert state.state == STATE_OFF


async def test_friendly_names(hass, mqtt_mock, setup_tasmota):
"""Test state update via MQTT."""
config = copy.deepcopy(DEFAULT_CONFIG)
Expand Down
Loading