_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
# Extract the 'value1' and 'value2' fields
value1=msg_json.get('value1')
# Parse 'value1' as a datetime
ifvalue1:
timestamp=int(value1)/1000.0
self._time=datetime.fromtimestamp(timestamp)
self._value1=value1
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
# Extract the 'value2' field
value2=msg_json.get('value2')
# Store 'value2' as the message if it exists
self._value2=value2ifvalue2else"None"
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
# Extract the EVENT field
event=msg_json.get('event')
ifeventisNone:
_LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
return
# Use the mapping to convert the event to the corresponding state
new_state=self._mapping.get(event)# Default to "None" if no mapping found
ifnew_stateisnotNone:
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
self._state=new_state
self._last_event=new_state# Update the last event
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
asyncdeftimeout(self):
"""Set the state to 'None' after a timeout."""
awaitasyncio.sleep(15)
self._state="None"
self._last_event="None"
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
self.async_schedule_update_ha_state()
classsleepdSoundSensor(RestoreEntity):
"""Representation of a sleepd - Sleep As Android Stats sensor for Sound Events."""
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
# Extract the EVENT field
event=msg_json.get('event')
ifeventisNone:
_LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
return
# Use the mapping to convert the event to the corresponding state
new_state=self._mapping.get(event)
ifnew_stateisnotNone:
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
self._state=new_state
self._last_event=new_state# Update the last event
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
# Extract the 'value1' and 'value2' fields
value1=msg_json.get('value1')
# Parse 'value1' as a datetime
ifvalue1:
timestamp=int(value1)/1000.0
self._time=datetime.fromtimestamp(timestamp)
self._value1=value1
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
# Extract the 'value2' field
value2=msg_json.get('value2')
# Store 'value2' as the message if it exists
self._value2=value2ifvalue2else"None"
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
asyncdeftimeout(self):
"""Set the state to 'None' after a timeout."""
awaitasyncio.sleep(15)
self._state="None"
self._last_event="None"
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
self.async_schedule_update_ha_state()
classsleepdSleepTrackingSensor(RestoreEntity):
"""Representation of a sleepd - Sleep As Android Stats sensor for Sleep Tracking."""
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
asyncdefmessage_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json=json.loads(msg.payload)
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
# Extract the EVENT field
event=msg_json.get('event')
ifeventisNone:
_LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
return
# Use the mapping to convert the event to the corresponding state
new_state=self._mapping.get(event)# Removed default to "None"
ifnew_stateisnotNone:# Only update state if a mapping is found
self._state=new_state
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
# Extract the EVENT field
event=msg_json.get('event')
ifeventisNone:
_LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
return
# Use the mapping to convert the event to the corresponding state
new_state=self._mapping.get(event)
ifnew_stateisnotNone:
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {new_state} for sensor {self.name}")
self._state=new_state
self._last_event=new_state# Update the last event
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
# Extract the 'value1' and 'value2' fields
value1=msg_json.get('value1')
# Parse 'value1' as a datetime
ifvalue1:
timestamp=int(value1)/1000.0
self._time=datetime.fromtimestamp(timestamp)
self._value1=value1
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Parsed 'value1' as datetime: {self._time} for sensor {self.name}")
# Extract the 'value2' field
value2=msg_json.get('value2')
# Store 'value2' as the message if it exists
self._value2=value2ifvalue2else"None"
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Stored 'value2' as message: {self._value2} for sensor {self.name}")
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
asyncdeftimeout(self):
"""Set the state to 'None' after a timeout."""
awaitasyncio.sleep(15)
self._state="None"
self._last_event="None"
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to 'None' due to timeout for sensor {self.name}")
self.async_schedule_update_ha_state()
classsleepdLullabySensor(RestoreEntity):
"""Representation of a sleepd - Sleep As Android Stats sensor for Lullaby."""
def__init__(self,hass,name,mapping,entry_id):
"""Initialize the sensor."""
self._state=None
self._name=name
self._hass=hass
self._mapping=mapping
self.entry_id=entry_id
@property
defunique_id(self):
"""Return a unique ID."""
returnf"sleepd_lullaby_sensor_{self._name}"
@property
defname(self):
"""Return the name of the sensor."""
returnf"sleepd {self._name} Lullaby"
@property
defstate(self):
"""Return the state of the sensor."""
returnself._state
@property
defdevice_info(self):
"""Return information about the device."""
return{
"identifiers":{(DOMAIN,self._name)},
"name":self._name,
"manufacturer":INTEGRATION_NAME,
"model":MODEL,
}
asyncdefasync_added_to_hass(self):
"""Run when entity about to be added."""
awaitsuper().async_added_to_hass()
# Load the previous state from the state machine
state=awaitself.async_get_last_state()
ifstate:
self._state=state.state
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
asyncdefmessage_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json=json.loads(msg.payload)
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
# Extract the EVENT field
event=msg_json.get('event')
ifeventisNone:
_LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
return
# Use the mapping to convert the event to the corresponding state
new_state=self._mapping.get(event,"None")# Default to "None" if no mapping found
self._state=new_state
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Saved state: {self._state} for sensor {self.name}")
classsleepdSleepStage(RestoreEntity):
"""Representation of a sleepd - Sleep As Android Stats sensor for Sleep Stage."""
def__init__(self,hass,name,mapping,entry_id):
"""Initialize the sensor."""
self._state=None
self._name=name
self._hass=hass
self._mapping=mapping
self.entry_id=entry_id
@property
defunique_id(self):
"""Return a unique ID."""
returnf"sleepd_sleep_stage_sensor_{self._name}"
@property
defname(self):
"""Return the name of the sensor."""
returnf"sleepd {self._name} Sleep Stage"
@property
defstate(self):
"""Return the state of the sensor."""
returnself._state
@property
defdevice_info(self):
"""Return information about the device."""
return{
"identifiers":{(DOMAIN,self._name)},
"name":self._name,
"manufacturer":INTEGRATION_NAME,
"model":MODEL,
}
asyncdefasync_added_to_hass(self):
"""Run when entity about to be added."""
awaitsuper().async_added_to_hass()
# Load the previous state from the state machine
state=awaitself.async_get_last_state()
ifstate:
self._state=state.state
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")
asyncdefmessage_received(msg):
"""Handle new MQTT messages."""
# Parse the incoming message
msg_json=json.loads(msg.payload)
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Received MQTT message: {msg_json} for sensor {self.name}")
# Extract the EVENT field
event=msg_json.get('event')
ifeventisNone:
_LOGGER.warning(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): No 'event' key in the MQTT message: {msg_json} for sensor {self.name}")
return
# Use the mapping to convert the event to the corresponding state
new_state=self._mapping.get(event,"None")# Default to "None" if no mapping found
self._state=new_state
_LOGGER.debug(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Set state to {new_state} for sensor {self.name}")
now=dt_util.utcnow()# Define 'now' before using it for logging
# Extract the 'event' from the incoming message
event=message.get('event')
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Extracted Event {event} from message.")
# Map the event to a known state, or "Unknown" if the event is not recognized
mapped_value=STATE_MAPPING.get(event,"Unknown")
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped {event} to {mapped_value}.")
# If the event could not be mapped to a known state, set the sensor state to "Unknown"
ifmapped_value=="Unknown":
self._state="Unknown"
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Event {event} could not be mapped to a known state. Setting sensor state to 'Unknown'.")
# If the mapped value is in the awake states, start or restart the awake timer and cancel the sleep timer
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped value {mapped_value} is in awake states. Starting or restarting awake timer and cancelling sleep timer.")
# If the mapped value is in the sleep states, start or restart the sleep timer and cancel the awake timer
_LOGGER.debug(f"{dt_util.as_local(now).strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Mapped value {mapped_value} is in sleep states. Starting or restarting sleep timer and cancelling awake timer.")
exceptExceptionase:
_LOGGER.error(f"Error processing message: {e}")
defset_state(self,state):
self._state=state
self.async_schedule_update_ha_state()
asyncdefasync_added_to_hass(self):
"""Run when entity about to be added."""
awaitsuper().async_added_to_hass()
# Load the previous state from the state machine
state=awaitself.async_get_last_state()
ifstate:
self._state=state.state
_LOGGER.info(f"{datetime.now().strftime('%H:%M:%S:%f')} (Line {inspect.currentframe().f_lineno}): Loaded state: {self._state} for sensor {self.name}")