def updateStates(self): for id in self.devices: device = self.devices[id] if not device: continue params = json.loads(device['sensor']) if (params['class'] == 'AirPurifier'): try: dev = AirPurifier(params['ip'], params['token']) state = str(dev.status()) sensors = state.split(' ') for sensor in sensors: sensor = sensor.replace(',', '').replace('>', '').split('=') if (len(sensor) == 2): type = sensor[0] value = sensor[1].replace('%', '').upper() if type == 'power': if value != device['state']: self.mySensors.saveSensorState(id, value) elif self.updateSensorByDevice(id, type, value): pass except DeviceException as e: self.log('Error getting device state: ' + str(e)) self.mySensors.saveSensorState(id, 'ERR') self.commit()
def log_air_purifier_events(): threading.Timer(60.0 * 10, log_air_purifier_events).start() values_keys = [ "power", "aqi", "average_aqi", "humidity", "temperature", "illuminance", "filter_life_remaining", "filter_hours_used", "motor_speed", ] air_purifier = AirPurifier(AIR_PURIFIER_IP, AIR_PURIFIER_TOKEN) status = air_purifier.status() data = {} for key in values_keys: data[key] = status.__getattribute__(key) data["mode"] = status.mode.value print(data) device_info = air_purifier.info() INFLUXDB_CLIENT.write_points([{ "measurement": "air_purifier", "tags": { "model": device_info.model, "firmware_version": device_info.firmware_version, "hardware_version": device_info.hardware_version, }, "fields": data, }])
async def async_create_miio_device_and_coordinator( hass: core.HomeAssistant, entry: config_entries.ConfigEntry): """Set up a data coordinator and one miio device to service multiple entities.""" model = entry.data[CONF_MODEL] host = entry.data[CONF_HOST] token = entry.data[CONF_TOKEN] name = entry.title device = None migrate = False if model not in MODELS_HUMIDIFIER and model not in MODELS_FAN: return _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) # Humidifiers if model in MODELS_HUMIDIFIER_MIOT: device = AirHumidifierMiot(host, token) migrate = True elif model in MODELS_HUMIDIFIER_MJJSQ: device = AirHumidifierMjjsq(host, token, model=model) migrate = True elif model in MODELS_HUMIDIFIER_MIIO: device = AirHumidifier(host, token, model=model) migrate = True # Airpurifiers and Airfresh elif model in MODEL_AIRPURIFIER_3C: device = AirPurifierMB4(host, token) elif model in MODELS_PURIFIER_MIOT: device = AirPurifierMiot(host, token) elif model.startswith("zhimi.airpurifier."): device = AirPurifier(host, token) elif model.startswith("zhimi.airfresh."): device = AirFresh(host, token) # Pedestal fans elif model == MODEL_FAN_P5: device = FanP5(host, token) elif model in MODELS_FAN_MIIO: device = Fan(host, token, model=model) else: _LOGGER.error( "Unsupported device found! Please create an issue at " "https://github.com/syssi/xiaomi_airpurifier/issues " "and provide the following data: %s", model, ) return if migrate: # Removing fan platform entity for humidifiers and migrate the name to the config entry for migration entity_registry = er.async_get(hass) entity_id = entity_registry.async_get_entity_id( "fan", DOMAIN, entry.unique_id) if entity_id: # This check is entities that have a platform migration only and should be removed in the future if migrate_entity_name := entity_registry.async_get( entity_id).name: hass.config_entries.async_update_entry( entry, title=migrate_entity_name) entity_registry.async_remove(entity_id)
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the air purifier from config.""" from miio import AirPurifier, DeviceException if PLATFORM not in hass.data: hass.data[PLATFORM] = {} host = config.get(CONF_HOST) name = config.get(CONF_NAME) token = config.get(CONF_TOKEN) _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5]) try: air_purifier = AirPurifier(host, token) xiaomi_air_purifier = XiaomiAirPurifier(name, air_purifier) hass.data[PLATFORM][host] = xiaomi_air_purifier except DeviceException: raise PlatformNotReady async_add_devices([xiaomi_air_purifier], update_before_add=True) @asyncio.coroutine def async_service_handler(service): """Map services to methods on XiaomiAirPurifier.""" method = SERVICE_TO_METHOD.get(service.service) params = { key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID } entity_ids = service.data.get(ATTR_ENTITY_ID) if entity_ids: target_air_purifiers = [ air for air in hass.data[PLATFORM].values() if air.entity_id in entity_ids ] else: target_air_purifiers = hass.data[PLATFORM].values() update_tasks = [] for air_purifier in target_air_purifiers: yield from getattr(air_purifier, method['method'])(**params) update_tasks.append(air_purifier.async_update_ha_state(True)) if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) descriptions = yield from hass.async_add_job( load_yaml_config_file, os.path.join(os.path.dirname(__file__), 'xiaomi_miio_services.yaml')) for air_purifier_service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[air_purifier_service].get( 'schema', AIRPURIFIER_SERVICE_SCHEMA) hass.services.async_register( DOMAIN, air_purifier_service, async_service_handler, description=descriptions.get(air_purifier_service), schema=schema)
async def async_create_miio_device_and_coordinator( hass: HomeAssistant, entry: ConfigEntry ) -> None: """Set up a data coordinator and one miio device to service multiple entities.""" model: str = entry.data[CONF_MODEL] host = entry.data[CONF_HOST] token = entry.data[CONF_TOKEN] name = entry.title device: MiioDevice | None = None migrate = False update_method = _async_update_data_default coordinator_class: type[DataUpdateCoordinator] = DataUpdateCoordinator if ( model not in MODELS_HUMIDIFIER and model not in MODELS_FAN and model not in MODELS_VACUUM and not model.startswith(ROBOROCK_GENERIC) and not model.startswith(ROCKROBO_GENERIC) ): return _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) # Humidifiers if model in MODELS_HUMIDIFIER_MIOT: device = AirHumidifierMiot(host, token) migrate = True elif model in MODELS_HUMIDIFIER_MJJSQ: device = AirHumidifierMjjsq(host, token, model=model) migrate = True elif model in MODELS_HUMIDIFIER_MIIO: device = AirHumidifier(host, token, model=model) migrate = True # Airpurifiers and Airfresh elif model in MODELS_PURIFIER_MIOT: device = AirPurifierMiot(host, token) elif model.startswith("zhimi.airpurifier."): device = AirPurifier(host, token) elif model.startswith("zhimi.airfresh."): device = AirFresh(host, token) elif model == MODEL_AIRFRESH_A1: device = AirFreshA1(host, token) elif model == MODEL_AIRFRESH_T2017: device = AirFreshT2017(host, token) elif ( model in MODELS_VACUUM or model.startswith(ROBOROCK_GENERIC) or model.startswith(ROCKROBO_GENERIC) ): device = RoborockVacuum(host, token) update_method = _async_update_data_vacuum coordinator_class = DataUpdateCoordinator[VacuumCoordinatorData] # Pedestal fans elif model in MODEL_TO_CLASS_MAP: device = MODEL_TO_CLASS_MAP[model](host, token) elif model in MODELS_FAN_MIIO: device = Fan(host, token, model=model) else: _LOGGER.error( "Unsupported device found! Please create an issue at " "https://github.com/syssi/xiaomi_airpurifier/issues " "and provide the following data: %s", model, ) return if migrate: # Removing fan platform entity for humidifiers and migrate the name to the config entry for migration entity_registry = er.async_get(hass) assert entry.unique_id entity_id = entity_registry.async_get_entity_id("fan", DOMAIN, entry.unique_id) if entity_id: # This check is entities that have a platform migration only and should be removed in the future if (entity := entity_registry.async_get(entity_id)) and ( migrate_entity_name := entity.name ): hass.config_entries.async_update_entry(entry, title=migrate_entity_name)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the miio fan device from config.""" from miio import Device, DeviceException if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {} host = config.get(CONF_HOST) name = config.get(CONF_NAME) token = config.get(CONF_TOKEN) model = config.get(CONF_MODEL) _LOGGER.info("Initializing with host %s (token %s...)", host, token[:5]) unique_id = None if model is None: try: miio_device = Device(host, token) device_info = miio_device.info() model = device_info.model unique_id = "{}-{}".format(model, device_info.mac_address) _LOGGER.info( "%s %s %s detected", model, device_info.firmware_version, device_info.hardware_version, ) except DeviceException: raise PlatformNotReady if model.startswith("zhimi.airpurifier."): from miio import AirPurifier air_purifier = AirPurifier(host, token) device = XiaomiAirPurifier(name, air_purifier, model, unique_id) elif model.startswith("zhimi.humidifier."): from miio import AirHumidifier air_humidifier = AirHumidifier(host, token, model=model) device = XiaomiAirHumidifier(name, air_humidifier, model, unique_id) elif model.startswith("zhimi.airfresh."): from miio import AirFresh air_fresh = AirFresh(host, token) device = XiaomiAirFresh(name, air_fresh, model, unique_id) else: _LOGGER.error( "Unsupported device found! Please create an issue at " "https://github.com/syssi/xiaomi_airpurifier/issues " "and provide the following data: %s", model, ) return False hass.data[DATA_KEY][host] = device async_add_entities([device], update_before_add=True) async def async_service_handler(service): """Map services to methods on XiaomiAirPurifier.""" method = SERVICE_TO_METHOD.get(service.service) params = { key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID } entity_ids = service.data.get(ATTR_ENTITY_ID) if entity_ids: devices = [ device for device in hass.data[DATA_KEY].values() if device.entity_id in entity_ids ] else: devices = hass.data[DATA_KEY].values() update_tasks = [] for device in devices: if not hasattr(device, method["method"]): continue await getattr(device, method["method"])(**params) update_tasks.append(device.async_update_ha_state(True)) if update_tasks: await asyncio.wait(update_tasks) for air_purifier_service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[air_purifier_service].get( "schema", AIRPURIFIER_SERVICE_SCHEMA) hass.services.async_register(DOMAIN, air_purifier_service, async_service_handler, schema=schema)
async def async_setup_entry(opp, config_entry, async_add_entities): """Set up the Fan from a config entry.""" entities = [] if config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE: if DATA_KEY not in opp.data: opp.data[DATA_KEY] = {} host = config_entry.data[CONF_HOST] token = config_entry.data[CONF_TOKEN] name = config_entry.title model = config_entry.data[CONF_MODEL] unique_id = config_entry.unique_id _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) if model in MODELS_PURIFIER_MIOT: air_purifier = AirPurifierMiot(host, token) entity = XiaomiAirPurifierMiot(name, air_purifier, config_entry, unique_id, allowed_failures=2) elif model.startswith("zhimi.airpurifier."): air_purifier = AirPurifier(host, token) entity = XiaomiAirPurifier(name, air_purifier, config_entry, unique_id) elif model in MODELS_HUMIDIFIER_MIOT: air_humidifier = AirHumidifierMiot(host, token) entity = XiaomiAirHumidifierMiot(name, air_humidifier, config_entry, unique_id) elif model.startswith("zhimi.humidifier."): air_humidifier = AirHumidifier(host, token, model=model) entity = XiaomiAirHumidifier(name, air_humidifier, config_entry, unique_id) elif model.startswith("zhimi.airfresh."): air_fresh = AirFresh(host, token) entity = XiaomiAirFresh(name, air_fresh, config_entry, unique_id) else: _LOGGER.error( "Unsupported device found! Please create an issue at " "https://github.com/syssi/xiaomi_airpurifier/issues " "and provide the following data: %s", model, ) return opp.data[DATA_KEY][host] = entity entities.append(entity) async def async_service_handler(service): """Map services to methods on XiaomiAirPurifier.""" method = SERVICE_TO_METHOD[service.service] params = { key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID } entity_ids = service.data.get(ATTR_ENTITY_ID) if entity_ids: entities = [ entity for entity in opp.data[DATA_KEY].values() if entity.entity_id in entity_ids ] else: entities = opp.data[DATA_KEY].values() update_tasks = [] for entity in entities: entity_method = getattr(entity, method["method"], None) if not entity_method: continue await entity_method(**params) update_tasks.append( opp.async_create_task(entity.async_update_op_state(True))) if update_tasks: await asyncio.wait(update_tasks) for air_purifier_service in SERVICE_TO_METHOD: schema = SERVICE_TO_METHOD[air_purifier_service].get( "schema", AIRPURIFIER_SERVICE_SCHEMA) opp.services.async_register(DOMAIN, air_purifier_service, async_service_handler, schema=schema) async_add_entities(entities, update_before_add=True)
def __init__(self, ip, token): self.ap = AirPurifier(ip=ip, token=token) self.status = self.ap.status() self.units = {} self.selectorData = {} return
class Helper(): def __init__(self, ip, token): self.ap = AirPurifier(ip=ip, token=token) self.status = self.ap.status() self.units = {} self.selectorData = {} return def createDomoticzDevices(self): Domoticz.Log("Creating devices in Domoticz") name = "Airpurifier" unit = 1 if unit not in Devices: Domoticz.Debug("Creating power switch") Domoticz.Device(Name="Power", Unit=unit, Image=7, TypeName="Switch").Create() else: Domoticz.Debug("Power switch already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "switch", "command": self.powerSwitch, "currentValue": self.powerSwitchCurrentValue, "dependantSwitch": { "unit": 2, "ifValue": "off", "setValue": 10 } } unit = 2 if unit not in Devices: Domoticz.Debug("Creating operation selector switch") Options = { "LevelActions": "||||", "LevelNames": "|Idle|Auto|Silent|Favorite", "LevelOffHidden": "true", "SelectorStyle": "1" } Domoticz.Device(Name="Operation selector", Unit=unit, Image=7, TypeName="Selector Switch", Options=Options).Create() else: Domoticz.Debug( "Operation selector switch already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "selector", "command": self.operationSelectorSwitch, "currentValue": self.operationSelectorSwitchCurrentValue, "dependantSwitch": { "unit": 1, "ifValue": "10", "setValue": "off" } } self.selectorData[unit] = { "idle": 10, "auto": 20, "silent": 30, "favorite": 40, "10": "idle", "20": "auto", "30": "silent", "40": "favorite" } unit = 3 if unit not in Devices: Domoticz.Debug("Creating led brightness selector switch") Options = { "LevelActions": "|||", "LevelNames": "|Off|Dim|Bright", "LevelOffHidden": "true", "SelectorStyle": "1" } Domoticz.Device(Name="Led brightness", Unit=unit, Image=7, TypeName="Selector Switch", Options=Options).Create() else: Domoticz.Debug( "Led brightness switch already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "selector", "command": self.ledBrightnessSwitch, "currentValue": self.ledBrightnessSwitchCurrentValue } self.selectorData[unit] = { "2": 10, "1": 20, "0": 30, "10": 2, "20": 1, "30": 0 } unit = 4 if unit not in Devices: Domoticz.Debug("Creating favorite level selector switch") Options = { "LevelActions": "||||||||||||||||", "LevelNames": "|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16", "LevelOffHidden": "true", "SelectorStyle": "1" } Domoticz.Device(Name="Favorite level", Unit=unit, Image=7, TypeName="Selector Switch", Options=Options).Create() else: Domoticz.Debug( "Favorite level switch already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "selector", "command": self.favoriteLevelSwitch, "currentValue": self.favoriteLevelSwitchCurrentValue } self.selectorData[unit] = { "1": 10, "2": 20, "3": 30, "4": 40, "5": 50, "6": 60, "7": 70, "8": 80, "9": 90, "10": 100, "11": 110, "12": 120, "13": 130, "14": 140, "15": 150, "16": 160, "10": 1, "20": 2, "30": 3, "40": 4, "50": 5, "60": 6, "70": 7, "80": 8, "90": 9, "100": 10, "110": 11, "120": 12, "130": 13, "140": 14, "150": 15, "160": 16 } unit = 5 if unit not in Devices: Domoticz.Debug("Creating air quality device") Options = {"Custom": "1;μg/m³"} Domoticz.Device(Name="Air quality", Unit=unit, Type=243, Subtype=31, Image=7, Options=Options).Create() else: Domoticz.Debug( "Air quality device already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "sensor", "currentValue": self.airQualityDeviceCurrentValue } unit = 6 if unit not in Devices: Domoticz.Debug("Creating temperature + humidity device") Domoticz.Device(Name="Temperature + humidity", Unit=unit, Type=82, Image=7).Create() else: Domoticz.Debug( "Temperature + humidity device already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "sensor", "currentValue": self.temperatureHumidityDeviceCurrentValue } unit = 7 if unit not in Devices: Domoticz.Debug("Creating filter life remaining device") Domoticz.Device(Name="Filter life remaining", Unit=unit, Type=243, Subtype=6, Image=7).Create() else: Domoticz.Debug( "Filter life remaining device already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "sensor", "currentValue": self.filterLifeRemainingDeviceCurrentValue } unit = 8 if unit not in Devices: Domoticz.Debug("Creating filter hours used device") Options = {"Custom": "1;hours"} Domoticz.Device(Name="Filter hours used", Unit=unit, Type=243, Subtype=31, Image=7, Options=Options).Create() else: Domoticz.Debug( "Filter hours used device already exists with unit ID: %d" % (unit)) self.units[unit] = { "type": "sensor", "currentValue": self.filterHoursUsedDeviceCurrentValue } return def runCommand(self, unit, command, level): updateValues = self.units[unit]["command"](unit, command, str(level)) self.updateDomoticzDevice(unit, updateValues["nValue"], updateValues["sValue"]) if "dependantSwitch" in self.units[unit] and self.units[unit][ "dependantSwitch"]["ifValue"] == updateValues["sValue"].lower( ): self.updateDomoticzDevice( self.units[unit]["dependantSwitch"]["unit"], updateValues["nValue"], self.units[unit]["dependantSwitch"]["setValue"]) return def powerSwitchCurrentValue(self): return self.status.power def powerSwitch(self, unit, command, level): nValue = 0 sValue = "Off" if command.lower() == "on": self.ap.on() nValue = 1 sValue = "On" else: self.ap.off() return {"nValue": nValue, "sValue": sValue} def operationSelectorSwitchCurrentValue(self): return self.status.mode.value def operationSelectorSwitch(self, unit, command, level): nValue = 0 sValue = OperationMode(self.selectorData[unit][level]) if sValue != "idle": nValue = 1 self.ap.set_mode(sValue) return {"nValue": nValue, "sValue": level} def ledBrightnessSwitchCurrentValue(self): return self.status.led_brightness.value def ledBrightnessSwitch(self, unit, command, level): ps = self.powerSwitchCurrentValue() nValue = 0 if ps.lower() == "off" else 1 sValue = LedBrightness(self.selectorData[unit][level]) self.ap.set_led_brightness(sValue) return {"nValue": nValue, "sValue": level} def favoriteLevelSwitchCurrentValue(self): return self.status.favorite_level def favoriteLevelSwitch(self, unit, command, level): ps = self.powerSwitchCurrentValue() nValue = 0 if ps.lower() == "off" else 1 sValue = self.selectorData[unit][level] self.ap.set_favorite_level(sValue) return {"nValue": nValue, "sValue": level} def airQualityDeviceCurrentValue(self): return self.status.aqi def temperatureHumidityDeviceCurrentValue(self): temp = self.status.temperature hum = self.status.humidity humStatus = 3 if hum < 25: humStatus = 2 elif hum < 40: humStatus = 1 elif hum < 60: humStatus = 0 return "%f;%f;%d" % (temp, hum, humStatus) def filterLifeRemainingDeviceCurrentValue(self): return self.status.filter_life_remaining def filterHoursUsedDeviceCurrentValue(self): return self.status.filter_hours_used def updateAirPurifierStatus(self): self.status = self.ap.status() def updateDomoticzDevice(self, unit, nValue, sValue): Domoticz.Debug("Updating Domoticz device %d: (%d,%s)" % (unit, nValue, sValue)) Devices[unit].Update(nValue=nValue, sValue=str(sValue)) def updateDomoticzDevices(self): self.updateAirPurifierStatus() for unit in self.units: unitType = self.units[unit]["type"] value = self.units[unit]["currentValue"]() ps = self.powerSwitchCurrentValue() nValue = 0 if ps.lower() == "off" else 1 sValue = value if unitType == "switch": nValue = 0 if value.lower() == "off" else 1 sValue = "On" if sValue else "Off" elif unitType == "sensor": nValue = 0 if unit in self.selectorData and ( str(sValue)).lower() in self.selectorData[unit]: sValue = self.selectorData[unit][(str(sValue)).lower()] self.updateDomoticzDevice(unit, nValue, sValue) return
import time from pymongo import MongoClient from miio import AirPurifier, DeviceException while True: try: #Connect to MongoDB client = MongoClient( "mongodb://<username>:<pw>@XXX.XXX.XXX.XXX:27017/admin" ) #<--------------------To config db = client['{}'.format('sensors')] write = db['{}'.format('xiaomi_AirPurifier')] #Conenct to AirPurifier, (IP, token) xm_airP = AirPurifier("192.168.0.XXX", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX") ############################# #Status data try: while True: #Get data status = xm_airP.status() #Creat JSON object for DB writeData = ({ 'aqi': int(status.aqi), 'humidity': int(status.humidity), 'illuminance':