Skip to content

Commit

Permalink
Fix some bugs. Replace mgm3_to_ppm to mgm3_to_ppb
Browse files Browse the repository at this point in the history
  • Loading branch information
Limych committed Apr 22, 2020
1 parent 2f65375 commit 632acfa
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 48 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@ jq300:
for JQ-300 only: PM 2.5.\
_Default value: all available devices_
**receive_tvoc_in_ppm**:\
**receive_tvoc_in_ppb**:\
_(boolean) (Optional)_\
By default, the cloud returns the TVOC value in `mg/m³` units. Setting this parameter to `True` allows to receive data in `ppm` units.\
By default, the cloud returns the TVOC value in `mg/m³` units. Setting this parameter to `True` allows to receive data in `ppb` units.\
_Default value: False_

**receive_hcho_in_ppm**:\
**receive_hcho_in_ppb**:\
_(boolean) (Optional)_\
By default, the cloud returns the HCHO (formaldehyde) value in `mg/m³` units. Setting this parameter to `True` allows to receive data in `ppm` units.\
By default, the cloud returns the HCHO (formaldehyde) value in `mg/m³` units. Setting this parameter to `True` allows to receive data in `ppb` units.\
_Default value: False_

## Contributions are welcome!
Expand Down
80 changes: 44 additions & 36 deletions custom_components/jq300/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
QUERY_TYPE_API, QUERY_TYPE_DEVICE, QUERY_METHOD_GET, BASE_URL_API, \
BASE_URL_DEVICE, USERAGENT_API, USERAGENT_DEVICE, QUERY_TIMEOUT, \
MSG_GENERIC_FAIL, MSG_LOGIN_FAIL, QUERY_METHOD_POST, MSG_BUSY, \
SENSORS, UPDATE_MIN_TIME, CONF_RECEIVE_TVOC_IN_PPM, \
CONF_RECEIVE_HCHO_IN_PPM, UNIT_PPM
SENSORS, UPDATE_MIN_TIME, CONF_RECEIVE_TVOC_IN_PPB, \
CONF_RECEIVE_HCHO_IN_PPB, UNIT_PPM, UNIT_MGM3, UNIT_PPB

_LOGGER = logging.getLogger(__name__)

Expand All @@ -39,8 +39,8 @@
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_DEVICES): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_RECEIVE_TVOC_IN_PPM, default=False): cv.boolean,
vol.Optional(CONF_RECEIVE_HCHO_IN_PPM, default=False): cv.boolean,
vol.Optional(CONF_RECEIVE_TVOC_IN_PPB, default=False): cv.boolean,
vol.Optional(CONF_RECEIVE_HCHO_IN_PPB, default=False): cv.boolean,
})
}, extra=vol.ALLOW_EXTRA)

Expand All @@ -57,11 +57,11 @@ async def async_setup(hass, config):
username = config[DOMAIN].get(CONF_USERNAME)
password = config[DOMAIN].get(CONF_PASSWORD)
devices = config[DOMAIN].get(CONF_DEVICES)
receive_tvoc_in_ppm = config[DOMAIN].get(CONF_RECEIVE_TVOC_IN_PPM)
receive_hcho_in_ppm = config[DOMAIN].get(CONF_RECEIVE_HCHO_IN_PPM)
receive_tvoc_in_ppb = config[DOMAIN].get(CONF_RECEIVE_TVOC_IN_PPB)
receive_hcho_in_ppb = config[DOMAIN].get(CONF_RECEIVE_HCHO_IN_PPB)

controller = JqController(
hass, username, password, receive_tvoc_in_ppm, receive_hcho_in_ppm)
hass, username, password, receive_tvoc_in_ppb, receive_hcho_in_ppb)
hass.data[DATA_JQ300][username] = controller
_LOGGER.info('Connected to cloud account %s', username)

Expand All @@ -85,8 +85,8 @@ class JqController:
"""JQ device controller"""

# pylint: disable=R0913
def __init__(self, hass, username, password, receive_tvoc_in_ppm,
receive_hcho_in_ppm):
def __init__(self, hass, username, password, receive_tvoc_in_ppb,
receive_hcho_in_ppb):
"""Initialize configured device."""
self.hass = hass
self.params = {
Expand All @@ -96,13 +96,21 @@ def __init__(self, hass, username, password, receive_tvoc_in_ppm,

self._username = username
self._password = password
self._receive_tvoc_in_ppm = receive_tvoc_in_ppm
self._receive_hcho_in_ppm = receive_hcho_in_ppm
self._receive_tvoc_in_ppb = receive_tvoc_in_ppb
self._receive_hcho_in_ppb = receive_hcho_in_ppb

self._available = False
self._session = requests.session()
self._devices = {}
self._sensors = {}
self._units = {}

for sensor_id, data in SENSORS.items():
if (receive_tvoc_in_ppb and sensor_id == 8) \
or (receive_hcho_in_ppb and sensor_id == 7):
self._units[sensor_id] = UNIT_PPB
else:
self._units[sensor_id] = data[1]

@property
def unique_id(self):
Expand All @@ -119,6 +127,11 @@ def available(self) -> bool:
"""Return True if account is available."""
return self._login()

@property
def units(self):
"""Get list of units for sensors."""
return self._units

@staticmethod
def _get_useragent(query_type) -> str:
"""Generate User-Agent for requests"""
Expand Down Expand Up @@ -208,6 +221,7 @@ def query(self, query_type, function: str,
elif query_type == QUERY_TYPE_DEVICE:
if int(response['returnCode']) != 0:
_LOGGER.error(MSG_GENERIC_FAIL)
self.params['uid'] = -1000
return None
else:
raise ValueError('Unknown query type "%s"' % query_type)
Expand Down Expand Up @@ -266,9 +280,9 @@ def get_sensors(self, device_id, force=False) -> Optional[dict]:

if not force and device_id in self._sensors \
and self._sensors[device_id][''] >= ts_overdue:
data = self._sensors[device_id].copy()
del data['']
return data
res = self._sensors[device_id].copy()
del res['']
return res

devices = self.get_devices_list()
_LOGGER.debug(devices)
Expand All @@ -285,28 +299,22 @@ def get_sensors(self, device_id, force=False) -> Optional[dict]:
if not ret:
return self.get_sensors(device_id, True) if not force else None

data = {}
res = {}
for sensor in ret['deviceValueVos']:
sensor_id = sensor['seq']
if sensor_id in SENSORS.keys() and sensor['content'] is \
not None and float(sensor['content']) > 0:
data[sensor_id] = float(sensor['content'])
if (self._receive_tvoc_in_ppm and sensor_id == 8) \
or (self._receive_hcho_in_ppm and sensor_id == 7):
data[sensor_id] = int(data[sensor_id] * 224)

self._sensors[device_id] = data.copy()
if sensor['content'] is None \
or float(sensor['content']) <= 0 \
or sensor_id not in SENSORS.keys():
continue

res[sensor_id] = float(sensor['content'])
if sensor_id == 8 and self._receive_tvoc_in_ppb:
res[sensor_id] *= 310 # M = 78.9516 g/mol
elif sensor_id == 7 and self._receive_hcho_in_ppb:
res[sensor_id] *= 814 # M = 30.026 g/mol
if self._units[sensor_id] != UNIT_MGM3:
res[sensor_id] = int(res[sensor_id])

self._sensors[device_id] = res.copy()
self._sensors[device_id][''] = tstamp
return data

def get_sensors_units(self):
"""Get list of sensors units."""
units = {}
for sensor_id, data in SENSORS.values():
if (self._receive_tvoc_in_ppm and sensor_id == 8) \
or (self._receive_hcho_in_ppm and sensor_id == 7):
units[sensor_id] = UNIT_PPM
else:
units[sensor_id] = data[1]

return units
return res
7 changes: 4 additions & 3 deletions custom_components/jq300/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

# Base component constants
DOMAIN = "jq300"
VERSION = "0.6.0"
VERSION = "0.7.0"
ISSUE_URL = "https://github.com/Limych/ha-jq300/issues"
ATTRIBUTION = None
DATA_JQ300 = 'jq300'

SUPPORT_LIB_URL = "https://github.com/Limych/jq300/issues/new/choose"

CONF_RECEIVE_TVOC_IN_PPM = 'receive_tvoc_in_ppm'
CONF_RECEIVE_HCHO_IN_PPM = 'receive_hcho_in_ppm'
CONF_RECEIVE_TVOC_IN_PPB = 'receive_tvoc_in_ppb'
CONF_RECEIVE_HCHO_IN_PPB = 'receive_hcho_in_ppb'

# Error strings
MSG_GENERIC_FAIL = 'Sorry.. Something went wrong...'
Expand All @@ -51,6 +51,7 @@
UNIT_MGM3 = 'mg/m³'
UNIT_UGM3 = 'µg/m³'
UNIT_PPM = 'ppm'
UNIT_PPB = 'ppb'

SENSORS = {
4: [
Expand Down
8 changes: 4 additions & 4 deletions custom_components/jq300/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ async def async_setup_platform(hass, config, async_add_entities,

account_id = discovery_info[CONF_USERNAME]
device_id = discovery_info[CONF_DEVICE_ID]
_LOGGER.debug('Setup sensors for device %s', device_id)

controller = hass.data[DATA_JQ300][account_id] # type: JqController
device = controller.get_devices_list()
_LOGGER.debug(device)
# _LOGGER.debug(device)
if not device:
_LOGGER.error("Can't receive devices list from cloud.")
return
Expand Down Expand Up @@ -79,7 +80,7 @@ def __init__(self, hass, controller, device, sensor_id, sensor_state,
self._name = "{0} {1}".format(
device['pt_name'], SENSORS.get(sensor_id)[0])
self._state = sensor_state
self._units = SENSORS.get(sensor_id)[1]
self._units = controller.units[sensor_id]
self._icon = 'mdi:{}'.format(SENSORS.get(sensor_id)[2])
self._unique_id = '{}-{}-{}'.format(
self._controller.unique_id, self._device_id, sensor_id)
Expand Down Expand Up @@ -119,8 +120,7 @@ def device_state_attributes(self):
attrs = {
ATTR_DEVICE_BRAND: self._device_brand,
ATTR_DEVICE_MODEL: self._device_model,
ATTR_DEVICE_ID: '{}-{}'.format(
self._controller.unique_id, self._device_id),
ATTR_DEVICE_ID: self._device_id,
}
return attrs

Expand Down
2 changes: 1 addition & 1 deletion tracker.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"jq300": {
"version": "0.6.0",
"version": "0.7.0",
"local_location": "/custom_components/jq300/__init__.py",
"remote_location": "https://raw.githubusercontent.com/Limych/ha-jq300/master/custom_components/jq300/__init__.py",
"visit_repo": "https://github.com/Limych/ha-jq300",
Expand Down

0 comments on commit 632acfa

Please sign in to comment.