Skip to content

Commit e06c1b5

Browse files
committed
v1.2.7b
Bi-directional settings change complete. Hopefully CGDN1 issue is resolved Removed settings display and power off time for CGDN1
1 parent e33d7f3 commit e06c1b5

File tree

3 files changed

+67
-42
lines changed

3 files changed

+67
-42
lines changed

custom_components/qingping_cgs1/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
CONF_PM25_OFFSET = "pm25_offset"
5555
CONF_PM10_OFFSET = "pm10_offset"
5656
CONF_NOISE_OFFSET = "noise_offset"
57-
CONF_TVOC_OFFSET = "tvoc_offset"
57+
CONF_TVOC_OFFSET = "tvoc_zoom"
5858
CONF_TVOC_INDEX_OFFSET = "tvoc_index_offset"
5959

6060
# Default values for device settings

custom_components/qingping_cgs1/number.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def async_setup_entry(
5050
# Add model-specific entities
5151
if model == "CGS1":
5252
entities.append(
53-
QingpingCGSxSensorOffsetNumber(coordinator, config_entry, mac, name, "TVOC Offset", CONF_TVOC_OFFSET, device_info, "ppb")
53+
QingpingCGSxSensorOffsetNumber(coordinator, config_entry, mac, name, "TVOC Offset", CONF_TVOC_OFFSET, device_info, "%")
5454
)
5555
elif model == "CGS2":
5656
entities.extend([
@@ -59,8 +59,8 @@ async def async_setup_entry(
5959
])
6060
elif model == "CGDN1":
6161
entities.extend([
62-
QingpingCGSxTimeNumber(coordinator, config_entry, mac, name, "Power Off Time", CONF_POWER_OFF_TIME, device_info, 0, 60, 1, 30, "minutes"),
63-
QingpingCGSxTimeNumber(coordinator, config_entry, mac, name, "Display Off Time", CONF_DISPLAY_OFF_TIME, device_info, 0, 300, 1, 30, "seconds"),
62+
#QingpingCGSxTimeNumber(coordinator, config_entry, mac, name, "Power Off Time", CONF_POWER_OFF_TIME, device_info, 0, 60, 1, 30, "minutes"),
63+
#QingpingCGSxTimeNumber(coordinator, config_entry, mac, name, "Display Off Time", CONF_DISPLAY_OFF_TIME, device_info, 0, 300, 1, 30, "seconds"),
6464
QingpingCGSxTimeNumber(coordinator, config_entry, mac, name, "Auto Sliding Time", CONF_AUTO_SLIDING_TIME, device_info, 0, 180, 5, 30, "seconds"),
6565
QingpingCGSxScreensaverTypeNumber(coordinator, config_entry, mac, name, device_info),
6666
])
@@ -110,6 +110,7 @@ async def async_set_native_value(self, value: float) -> None:
110110

111111
# Publish setting change to device
112112
from .sensor import publish_setting_change
113+
113114
if self._offset_key == CONF_TEMPERATURE_OFFSET:
114115
if self._attr_native_unit_of_measurement == UnitOfTemperature.FAHRENHEIT:
115116
# Convert to Fahrenheit
@@ -223,7 +224,11 @@ async def async_set_native_value(self, value: int) -> None:
223224

224225
# Publish setting change to device
225226
from .sensor import publish_setting_change
226-
await publish_setting_change(self.hass, self._mac, self._offset_key, int(value))
227+
if self._offset_key == CONF_TVOC_OFFSET:
228+
device_value = int(value * 10)
229+
else:
230+
device_value = int(value)
231+
await publish_setting_change(self.hass, self._mac, self._offset_key, device_value)
227232

228233
async def async_added_to_hass(self) -> None:
229234
"""Run when entity about to be added to hass."""

custom_components/qingping_cgs1/sensor.py

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async def _update_settings_from_device(hass: HomeAssistant, config_entry: Config
110110
"pm25_offset": (CONF_PM25_OFFSET, int),
111111
"pm10_offset": (CONF_PM10_OFFSET, int),
112112
"noise_offset": (CONF_NOISE_OFFSET, int),
113-
"tvoc_offset": (CONF_TVOC_OFFSET, int),
113+
"tvoc_zoom": (CONF_TVOC_OFFSET, lambda x: round(x / 10, 1)),
114114
"tvoc_index_offset": (CONF_TVOC_INDEX_OFFSET, int),
115115
# CGDN1 specific settings
116116
"power_off_time": (CONF_POWER_OFF_TIME, int),
@@ -219,19 +219,31 @@ async def async_update_data():
219219
def message_received(message):
220220
"""Handle new MQTT messages."""
221221
try:
222+
_LOGGER.warning("=== MQTT MESSAGE RECEIVED === Topic: %s", message.topic)
223+
222224
payload = json.loads(message.payload)
225+
_LOGGER.warning("Payload type: %s", type(payload))
226+
223227
if not isinstance(payload, dict):
224228
_LOGGER.error("Payload is not a dictionary")
225229
return
226230

231+
# Check message type first - type 28 (settings) messages don't include MAC
232+
message_type = payload.get("type")
233+
234+
# For messages with MAC, verify it matches
227235
received_mac = payload.get("mac", "").replace(":", "").upper()
228236
expected_mac = mac.replace(":", "").upper()
229237

230-
if received_mac != expected_mac:
238+
_LOGGER.warning("Received MAC: %s, Expected MAC: %s, Type: %s", received_mac, expected_mac, message_type)
239+
240+
# Skip MAC check for type 28 (settings) messages as they don't include MAC
241+
# We're subscribed to this device's specific topic, so we know it's for us
242+
if received_mac and received_mac != expected_mac:
231243
_LOGGER.debug("Received message for a different device. Expected: %s, Got: %s", expected_mac, received_mac)
232244
return
233245

234-
_LOGGER.debug("Processing MQTT message for device %s", mac)
246+
_LOGGER.warning("Processing MQTT message for device %s", mac)
235247

236248
# Update timestamp first - any message from device means it's online
237249
current_timestamp = int(time.time())
@@ -247,25 +259,26 @@ def message_received(message):
247259
if device_type is not None:
248260
if type_sensor.hass:
249261
type_sensor.update_type(device_type)
250-
251-
# Log all message types for debugging
252-
message_type = payload.get("type")
253-
_LOGGER.info("Received MQTT message type: %s", message_type)
254262

255263
mac_address = payload.get("mac")
256264
if mac_address is not None:
257265
if mac_sensor.hass:
258266
mac_sensor.update_mac(mac_address)
259267

260-
# Handle type 28 messages (device settings update)
261-
message_type = payload.get("type")
268+
# Handle type 28 messages (device settings update) - Check BEFORE sensorData
269+
_LOGGER.warning("=== MESSAGE TYPE: %s ===", message_type)
270+
262271
if message_type == 28 or message_type == "28":
263-
_LOGGER.info("Received type 28 settings update from device")
272+
_LOGGER.error("!!! TYPE 28 SETTINGS UPDATE DETECTED !!!")
273+
_LOGGER.error("Full payload: %s", json.dumps(payload, indent=2))
264274
settings = payload.get("setting", {})
265-
_LOGGER.info("Settings in payload: %s", settings)
275+
_LOGGER.error("Settings extracted: %s", settings)
266276
if settings:
277+
_LOGGER.error("!!! CREATING TASK TO UPDATE SETTINGS !!!")
267278
hass.async_create_task(_update_settings_from_device(hass, config_entry, settings, model))
268-
return
279+
else:
280+
_LOGGER.error("!!! TYPE 28 HAS NO SETTINGS DICT !!!")
281+
return # Don't process as sensor data
269282

270283
sensor_data = payload.get("sensorData")
271284
if not isinstance(sensor_data, list) or not sensor_data:
@@ -322,36 +335,41 @@ def message_received(message):
322335
await mqtt.async_subscribe(
323336
hass, f"{MQTT_TOPIC_PREFIX}/{mac}/up", message_received, 1
324337
)
338+
_LOGGER.warning("=== SUBSCRIBED TO: %s/%s/up ===", MQTT_TOPIC_PREFIX, mac)
339+
340+
341+
342+
343+
344+
345+
325346

326-
# CGDN1-specific: Subscribe to any message for this device to detect when it comes online
327-
# CGDN1 doesn't always send full sensor data on power-on like CGS1/CGS2
328-
if model == "CGDN1":
329-
@callback
330-
def device_alive_check(message):
331-
"""Detect any MQTT activity from CGDN1 device."""
332-
try:
333-
_LOGGER.debug("CGDN1 device activity detected on topic: %s", message.topic)
334-
# Any MQTT activity from this device means it's alive
335-
if status_sensor.hass:
336-
current_time = int(time.time())
337-
if status_sensor._last_timestamp == 0 or (current_time - status_sensor._last_timestamp) > 60:
338-
_LOGGER.info("CGDN1 device %s appears to be online, updating status", mac)
339-
status_sensor.update_timestamp(current_time)
340-
# Trigger a config publish to get fresh data
341-
asyncio.create_task(sensors[5].publish_config())
342-
except Exception as e:
343-
_LOGGER.error("Error in CGDN1 device alive check: %s", str(e))
344-
345-
await mqtt.async_subscribe(
346-
hass, f"{MQTT_TOPIC_PREFIX}/{mac}/#", device_alive_check, 1
347-
)
347+
348+
349+
350+
351+
352+
353+
354+
355+
356+
357+
358+
359+
360+
361+
362+
363+
364+
365+
366+
# Note: CGDN1 devices are handled the same as other models
367+
# Status is determined solely by received MQTT messages, not by config publishes
348368

349369
# Set up timer for periodic publishing
350370
async def publish_config_wrapper(*args):
351371
if await ensure_mqtt_connected(hass):
352-
# Force status to online when we publish config
353-
if status_sensor.hass:
354-
status_sensor.update_timestamp(int(time.time()))
372+
# Don't force status to online - let actual device messages determine status
355373
await sensors[5].publish_config()
356374
else:
357375
_LOGGER.error("Failed to connect to MQTT for periodic config publish")
@@ -426,6 +444,8 @@ async def _publish_config_on_status_change(self):
426444
"""Publish config when status changes from offline to online."""
427445
if not self.hass:
428446
return
447+
# Add a small delay to let the device fully come online
448+
await asyncio.sleep(2)
429449
sensors = self.hass.data[DOMAIN][self._config_entry.entry_id].get("sensors", [])
430450
for sensor in sensors:
431451
if isinstance(sensor, QingpingCGSxSensor):

0 commit comments

Comments
 (0)