Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Yonsm Up to 0.94 67dd2f5 Jun 7, 2019
1 contributor

Users who have contributed to this file

212 lines (179 sloc) 7.35 KB
import asyncio
import json
import logging
import random
import time
import voluptuous as vol
from datetime import timedelta, datetime
from homeassistant.components.weather import (
ATTR_FORECAST_CONDITION, ATTR_FORECAST_PRECIPITATION, ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW, ATTR_FORECAST_TIME, ATTR_FORECAST_WIND_SPEED,
ATTR_FORECAST_WIND_BEARING,
PLATFORM_SCHEMA, WeatherEntity)
from homeassistant.const import (
CONF_NAME, CONF_LONGITUDE, CONF_LATITUDE, TEMP_CELSIUS,
CONF_SCAN_INTERVAL, STATE_UNKNOWN)
from homeassistant.helpers.event import async_track_time_interval
import homeassistant.helpers.config_validation as cv
#from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(minutes=1)
USER_AGENT = 'ColorfulCloudsPro/3.2.2 (iPhone; iOS 11.3; Scale/3.00)'
DEVIEC_ID = '5F544F93-44F1-43C9-94B2-%012X' % random.randint(0, 0xffffffffffff)
WEATHER_ICONS = {
'CLEAR_DAY': 'sunny', # 晴(白天)
'CLEAR_NIGHT': 'clear-night', # 晴(夜间)
'PARTLY_CLOUDY_DAY': 'partlycloudy', # 白天多云
'PARTLY_CLOUDY_NIGHT': 'partlycloudy', # 夜间多云
'CLOUDY': 'cloudy', #
'RAIN': 'rainy', #
'SNOW': 'snowy', #
'WIND': 'windy', # 大风
'FOG': 'fog', #
# 'HAZE': #雾霾
'SLEET': 'snowy-rainy' # 雨夹雪
# 'HAIL': hail', #冰雹
# 'LIGHTNING': 'lightning', #雷电
# 'LIGHTNING-RAINY': 'lightning-rainy', #雷阵雨
# 'POURING': 'pouring', #暴雨
# 'WINDY-VARIANT': 'windy-variant', #有风
}
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default='CaiYun'): cv.string,
vol.Optional(CONF_LONGITUDE): cv.longitude,
vol.Optional(CONF_LATITUDE): cv.latitude,
})
async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Set up the Caiyun sensor."""
name = config.get(CONF_NAME)
longitude = str(config.get(CONF_LONGITUDE, hass.config.longitude))
latitude = str(config.get(CONF_LATITUDE, hass.config.latitude))
async_add_devices([CaiYunWeather(name, hass, longitude, latitude)], True)
class CaiYunWeather(WeatherEntity):
def __init__(self, name, hass, longitude, latitude):
self._name = name
self._hass = hass
self._longitude = longitude
self._latitude = latitude
self._data = {}
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def icon(self):
return self._data.get('dash_icon')
@property
def condition(self):
"""Return the current condition."""
return self._data.get('condition')
@property
def temperature(self):
"""Return the platform temperature."""
return self._data.get('temperature')
@property
def temperature_unit(self):
"""Return the unit of measurement."""
return TEMP_CELSIUS
@property
def pressure(self):
"""Return the pressure."""
return self._data.get('pressure')
@property
def humidity(self):
"""Return the humidity."""
return self._data.get('humidity')
@property
def wind_speed(self):
"""Return the wind speed."""
return self._data.get('wind_speed')
@property
def wind_bearing(self):
"""Return the wind bearing."""
return self._data.get('wind_bearing')
@property
def ozone(self):
"""Return the ozone level."""
return self._data.get('ozone')
@property
def attribution(self):
"""Return the attribution."""
return self._data['attribution']
@property
def visibility(self):
"""Return the visibility."""
return self._data.get('visibility')
@property
def forecast(self):
return self._data.get('forecast')
@property
def available(self):
return bool(self._data)
@property
def state_attributes(self):
"""Return the state attributes."""
attributes = super().state_attributes
attributes['pm25'] = self._data.get('pm25')
return attributes
# @Throttle(timedelta(minutes=20))
async def async_update(self):
"""Update Condition and Forecast."""
data = {}
try:
headers = {'User-Agent': USER_AGENT,
'Accept': 'application/json',
'Accept-Language': 'zh-Hans-CN;q=1'}
url = "http://api.caiyunapp.com/v2/UR8ASaplvIwavDfR/%s,%s/" \
"weather?lang=zh_CN&tzshift=28800&timestamp=%d" \
"&hourlysteps=384&dailysteps=16&alert=true&device_id=%s" % \
(self._longitude, self._latitude, int(time.time()), DEVIEC_ID)
_LOGGER.info('getWeatherData: %s', url)
session = self._hass.helpers.aiohttp_client.async_get_clientsession()
async with session.get(url, headers=headers) as response:
json = await response.json()
#_LOGGER.info('gotWeatherData: %s', json)
result = json['result']
realtime = result['realtime']
if realtime['status'] != 'ok':
raise
# https://open.caiyunapp.com/%E5%AE%9E%E5%86%B5%E5%A4%A9%E6%B0%94%E6%8E%A5%E5%8F%A3/v2.2
skycon = realtime['skycon']
data['condition'] = WEATHER_ICONS[skycon] if skycon in WEATHER_ICONS else 'exceptional'
#data['dash_icon'] = 'mdi:weather-' + data['condition']
data['temperature'] = round(realtime['temperature'])
data['humidity'] = int(realtime['humidity'] * 100)
data['pressure'] = int(realtime['pres'])
wind = realtime.get('wind')
if wind:
data['wind_speed'] = wind.get('speed')
data['wind_bearing'] = wind.get('direction')
data['ozone'] = realtime.get('o3')
data['visibility'] = realtime.get('visibility')
data['attribution'] = result['forecast_keypoint']
data['pm25'] = realtime.get('pm25')
forecasts = {}
daily = result['daily']
for key in ['temperature', 'skycon', 'wind', 'precipitation']:
for v in daily[key]:
date = v['date']
forecast = forecasts.get(date)
if forecast is None:
forecast = {ATTR_FORECAST_TIME: datetime.strptime(date, '%Y-%m-%d')}
forecasts[date] = forecast
if key == 'temperature':
forecast[ATTR_FORECAST_TEMP] = v['avg']
forecast[ATTR_FORECAST_TEMP_LOW] = v['min']
elif key == 'skycon':
skycon = v['value']
forecast[ATTR_FORECAST_CONDITION] = WEATHER_ICONS[skycon] if skycon in WEATHER_ICONS else 'exceptional'
elif key == 'wind':
forecast[ATTR_FORECAST_WIND_BEARING] = v['avg']['direction']
forecast[ATTR_FORECAST_WIND_SPEED] = v['avg']['speed']
elif key == 'precipitation':
forecast[ATTR_FORECAST_PRECIPITATION] = v['avg']
data['forecast'] = sorted(forecasts.values(), key=lambda k: k[ATTR_FORECAST_TIME])
except:
import traceback
_LOGGER.error('exception: %s', traceback.format_exc())
self._data = data
You can’t perform that action at this time.