| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- <?php
- namespace Heanup\Library\WeatherAdapt;
- use Heanup\App\Api\Config\CityToCoordinate;
- use Heanup\App\Api\Config\GlobalConfig;
- use Heanup\Library\Curl;
- use Heanup\Library\Redis;
- use Heanup\Library\Warming;
- /**
- * Class mixedAdapter 混合接口(彩云+天气网)
- * @package Heanup\Library\WeatherAdapt
- */
- class mixedAdapter implements Weather
- {
- private $city_id;
- private $location;
- private $weather_code = [
- 0 => '晴',
- 1 => '多云',
- 2 => '阴',
- 3 => '阵雨',
- 4 => '雷阵雨',
- 5 => '雷阵雨伴有冰雹',
- 6 => '雨夹雪',
- 7 => '小雨',
- 8 => '中雨',
- 9 => '大雨',
- 10 => '暴雨',
- 11 => '大暴雨',
- 12 => '特大暴雨',
- 13 => '阵雪',
- 14 => '小雪',
- 15 => '中雪',
- 16 => '大雪',
- 17 => '暴雪',
- 18 => '雾',
- 19 => '冻雨',
- 20 => '沙尘暴',
- 21 => '小到中雨',
- 22 => '中到大雨',
- 23 => '大到暴雨',
- 24 => '暴雨到大暴雨',
- 25 => '大暴雨到特大暴雨',
- 26 => '小到中雪',
- 27 => '中到大雪',
- 28 => '大到暴雪',
- 29 => '浮尘',
- 30 => '扬沙',
- 31 => '强沙尘暴',
- 53 => '霾',
- 99 => '无',
- 32 => '浓雾',
- 49 => '强浓雾',
- 54 => '中度霾',
- 55 => '重度霾',
- 56 => '严重霾',
- 57 => '大雾',
- 58 => '特强浓雾',
- 301 => '雨',
- 302 => '雪',
- ];
- /**
- * @param $city_id
- * @return mixed
- */
- public function getWeatherData($city_id)
- {
- $this->city_id = $city_id;
- // $city_id = is_numeric($city_id) ? ("CN" . $city_id) : $city_id;
- $key = $this->getKey();
- $caiyun_version = GlobalConfig::getData("caiyun_version");
- $url = sprintf("https://api.caiyunapp.com/v%s/%s/%s/weather_2.json?alert=true&dailysteps=15", $caiyun_version, $key, $this->getCoodinate($city_id));
- $data1 = Curl::get($url);
- $data1 = json_decode($data1, true);
- $data2=Redis::instance()->get("weather:$city_id");
- if (!$data2){
- $url = sprintf("https://apip.weatherdt.com/plugin/data?key=FKh9Y6PdLP&location=%s", $city_id);
- $data2 = Curl::get($url);
- $data2 = json_decode($data2, true);
- Redis::instance()->set("weather:$city_id", $data2,7200);
- }
- $data = $this->parseData($data1, $data2);
- $i = 0;
- while ($data['Weather']['now']['cond_txt'] == "" && $i < 2) {//数据有误,重试3次
- $log_file = APP_DIR . "/logs/" . date("Ymd") . "_null.log";
- file_put_contents($log_file, sprintf("%s\t\tcity_id:%s", date("Y-m-d H:i:s"), $city_id) . "\t\tdata1:" . json_encode($data1) . "\t\tdata2:".json_encode($data2)."\r\n", FILE_APPEND);
- Warming::semdMail("no_data", "混合接口", ALERT_TOTAL, $log_file);
- $url = sprintf("https://api.caiyunapp.com/v%s/%s/%s/weather_2.json?alert=true&dailysteps=15", $caiyun_version, $key, $this->getCoodinate($city_id));
- $data1 = Curl::get($url);
- $url = sprintf("https://apip.weatherdt.com/plugin/data?key=FKh9Y6PdLP&location=%s", $city_id);
- $data2 = Curl::get($url);
- $data1 = json_decode($data1, true);
- $data2 = json_decode($data2, true);
- Redis::instance()->set("weather:$city_id", $data2,7200);
- $data = $this->parseData($data1, $data2);
- $i++;
- }
- return $data;
- }
- private function getKey()
- {
- $keys = GlobalConfig::getData("caiyun_key");
- $key = date("Ymd_") . $keys;
- Redis::instance()->incr($key);
- return $keys;
- }
- /**
- *
- * @param $data
- * @param null $data2
- * @return array
- */
- public function parseData($data, $data2 = null)
- {
- $originData = $data;
- $return = [];
- $weather = [];
- $weather['basic'] = [
- 'location' => $this->location,
- 'city_code' => $this->city_id,
- 'update' => date("Y-m-d H:i", $data['server_time'])
- ];
- $weather['status'] = $originData['status'] ?: "ok";
- $result = $originData['result'];
- // $weather['key'] = $k;
- $weather['air_now_city'] = [
- "aqi" => (string)$result['realtime']['air_quality']['aqi']['chn'] ?? "", // ->a3
- "qlty" => (string)$result['realtime']['air_quality']['description']['chn'] ?? "", // ->a4
- "pm25" => (string)$result['realtime']['air_quality']['pm25'] ?? "", // ->a5
- "pm10" => (string)$result['realtime']['air_quality']['pm10'] ?? "", // ->a6
- "no2" => (string)$result['realtime']['air_quality']['no2'] ?? "", // ->a7
- "so2" => (string)$result['realtime']['air_quality']['so2'] ?? ""
- ];
- $weather['alarm'] = [
- "level" => "", // ->a9
- "link" => $this->getAlert($result['alert']['content'][0]['code']), // ->b1
- "type" => "", // ->b2
- 'alertId' => (string)$result['alert']['content'][0]['alertId'] ?? "",
- "title" => (string)$result['alert']['content'][0]['title'] ?? "",// ->z2
- "description" => (string)($result['alert']['content'][0]['description'] ? $result['alert']['content'][0]['description'] . sprintf("(来源:%s)", $result['alert']['content'][0]['source']) : ""), // ->z3
- "pubtimestamp" => (string)($result['alert']['content'] ? date("Y-m-d H:i", $result['alert']['content'][0]['pubtimestamp']) : ""), // ->z4
- "location" => (string)$result['alert']['content'][0]['location'] ?? "", // ->z5
- "status" => (string)$result['alert']['content'][0]['status'] ?? "" // ->z6
- ];
- $weather['now'] = [
- "cond_txt" => $this->getSkycon($result['realtime']['skycon']), // ->b3
- "fl" => (string)(intval($result['realtime']['apparent_temperature']) ?: ""),// ->b4
- "hum" => (string)intval($result['realtime']['humidity'] * 100), // ->b5
- "pres" => (string)intval($result['realtime']['pressure'] / 100), // ->b6
- "tmp" => (string)(intval($result['realtime']['temperature']) ?: ""), // ->b7
- "vis" => (string)$result['realtime']['visibility'] ?: "", // ->b8
- "wind_dir" => (string)$this->getWindDirect($result['realtime']['wind']['direction']) ?: "", // ->b9
- "wind_sc" => (string)$this->getWindSpeed($result['realtime']['wind']['speed'])['level'] ?: "", // ->c1
- "sr" => (string)$result['daily']['astro'][0]['sunrise']['time'], // ->c2
- "ss" => (string)$result['daily']['astro'][0]['sunset']['time'], // ->c3
- 'forecast_keypoint' => (string)$result['forecast_keypoint'] ?? "",
- 'description' => (string)$result['hourly']['description'] ?? "",
- ];
- if (!empty($result['daily'])) {
- if (!empty($data2['forecast'])) {
- $i = 0;
- $date = date("Y-m-d", strtotime($data2['forecast']['date']));
- foreach ($data2['forecast']['forecast'] as $key => $value) {
- $temp = [
- "cond_txt_d" => $this->weather_code[intval($value['tqw_code_d'])] ?: ($value['tqw_code_d'] ?: ""),//$value['tqw_code_d'] ?: "",
- "cond_txt_n" => $this->weather_code[intval($value['tqw_code_n'])] ?: ($value['tqw_code_n'] ?: ""),//$value['tqw_code_n'] ?: "",
- "date" => date("Y-m-d", strtotime("+$i days", strtotime($date))),
- "tmp_max" => $value['tmp_max'] ?: "",
- "tmp_min" => $value['tmp_min'] ?: "",
- "wind_dir" => $value['wind_dir_d_txt'] ?: "",
- "wind_sc" => $value['wind_sc_d_txt'] ?: "",
- ];
- $i++;
- $weather['daily_forecast'][] = $temp;
- }
- }
- $j = 0;
- foreach ($result['daily']['skycon_08h_20h'] as $key => $value) {
- if ($j < $i) {
- $j++;
- continue;
- }
- $temp = [
- "cond_txt_d" => $this->getSkycon($value['value']),
- "cond_txt_n" => $this->getSkycon($result['daily']['skycon_20h_32h'][$key]['value']),
- "date" => date("Y-m-d", strtotime($value['date'])),
- "tmp_max" => (string)intval($result['daily']['temperature'][$key]['max']),
- "tmp_min" => (string)intval($result['daily']['temperature'][$key]['min']),
- "wind_dir" => (string)$this->getWindDirect($result['daily']['wind'][$key]['avg']['direction']),
- "wind_sc" => (string)$this->getWindSpeed($result['daily']['wind'][$key]['avg']['speed'])['level'],
- ];
- $weather['daily_forecast'][] = $temp;
- }
- }
- if (!empty($result['hourly'])) {
- $i = 0;
- foreach ($result['hourly']['temperature'] as $key => $value) {
- if ($i >= 24) {
- break;
- }
- $i++;
- $temp = [
- 'cond_txt' => $this->getSkycon($result['hourly']['skycon'][$key]['value']),
- 'time' => date("Y-m-d H:i", strtotime($value['datetime'])),
- 'tmp' => (string)intval($value['value']),
- ];
- $weather['hourly'][] = $temp;
- }
- }
- $weather['lifestyle'] = [
- [
- 'type' => 'flu',
- 'brf' => $result['daily']['life_index']['coldRisk'][0]['desc'],
- 'txt' => ''
- ], [
- 'type' => 'cw',
- 'brf' => $result['daily']['life_index']['carWashing'][0]['desc'],
- 'txt' => ''
- ], [
- 'type' => 'uv',
- 'brf' => $result['daily']['life_index']['ultraviolet'][0]['desc'],
- 'txt' => ''
- ], [
- 'type' => 'comf',
- 'brf' => $result['daily']['life_index']['comfort'][0]['desc'],
- 'txt' => ''
- ], [
- 'type' => 'drsg',
- 'brf' => $result['daily']['life_index']['dressing'][0]['desc'],
- 'txt' => ''
- ],
- ];
- $return['Weather'] = $weather;
- $return['source'] = "caiyun";
- return $return;
- }
- /**
- * @param $code
- * @return array|mixed|string
- */
- private function getCoodinate($code)
- {
- $key = "coodinateData";
- $coodinate = Redis::instance()->hGet($key, $code);
- // unset($coodinate);
- if (!$coodinate['lo'] || !$coodinate['la']) {
- $coodinate = CityToCoordinate::getData($code);
- if (!empty($coodinate)) {
- // $coodinate = $coodinate['lo'] . "," . $coodinate['la'];
- Redis::instance()->hSet($key, $code, $coodinate);
- }
- }
- $this->location = $coodinate['location'];
- return $coodinate['lo'] . "," . $coodinate['la'];
- }
- /**
- * 获取风向
- * @param $degree
- * @return mixed
- */
- private function getWindDirect($degree)
- {
- $directArr = ["北风", "东北风", "东北风", "东北风", "东风", "东南风", "东南风", "东南风", "南风", "西南风", "西南风", "西南风", "西风", "西北风", "西北风", "西北风"];
- $index = 0;
- if (348.75 <= $degree && $degree <= 360) {
- $index = 0;
- } else {
- if (0 <= $degree && $degree <= 11.25) {
- $index = 0;
- } else if (11.25 < $degree && $degree <= 33.75) {
- $index = 1;
- } else if (33.75 < $degree && $degree <= 56.25) {
- $index = 2;
- } else if (56.25 < $degree && $degree <= 78.75) {
- $index = 3;
- } else if (78.75 < $degree && $degree <= 101.25) {
- $index = 4;
- } else if (101.25 < $degree && $degree <= 123.75) {
- $index = 5;
- } else if (123.75 < $degree && $degree <= 146.25) {
- $index = 6;
- } else if (146.25 < $degree && $degree <= 168.75) {
- $index = 7;
- } else if (168.75 < $degree && $degree <= 191.25) {
- $index = 8;
- } else if (191.25 < $degree && $degree <= 213.75) {
- $index = 9;
- } else if (213.75 < $degree && $degree <= 236.25) {
- $index = 10;
- } else if (236.25 < $degree && $degree <= 258.75) {
- $index = 11;
- } else if (258.75 < $degree && $degree <= 281.25) {
- $index = 12;
- } else if (281.25 < $degree && $degree <= 303.75) {
- $index = 13;
- } else if (303.75 < $degree && $degree <= 326.25) {
- $index = 14;
- } else if (326.25 < $degree && $degree < 348.75) {
- $index = 15;
- }
- }
- return $directArr[$index];
- }
- private function getWindSpeed($speed)
- {
- $wind = [
- 'name' => '无风',
- 'level' => 0
- ];
- if ($speed > 1 && $speed <= 5) {
- $wind = [
- 'name' => '软风',
- 'level' => 1
- ];
- }
- if ($speed > 5 && $speed <= 11) {
- $wind = [
- 'name' => '轻风',
- 'level' => 2
- ];
- }
- if ($speed > 11 && $speed <= 19) {
- $wind = [
- 'name' => '微风',
- 'level' => 3
- ];
- }
- if ($speed > 19 && $speed <= 28) {
- $wind = [
- 'name' => '和风',
- 'level' => 4
- ];
- }
- if ($speed > 28 && $speed <= 38) {
- $wind = [
- 'name' => '清风',
- 'level' => 5
- ];
- }
- if ($speed > 38 && $speed <= 49) {
- $wind = [
- 'name' => '强风',
- 'level' => 6
- ];
- }
- if ($speed > 49 && $speed <= 61) {
- $wind = [
- 'name' => '劲风',
- 'level' => 7
- ];
- }
- if ($speed > 61 && $speed <= 74) {
- $wind = [
- 'name' => '大风',
- 'level' => 8
- ];
- }
- if ($speed > 74 && $speed <= 88) {
- $wind = [
- 'name' => '烈风',
- 'level' => 9
- ];
- }
- if ($speed > 88 && $speed <= 102) {
- $wind = [
- 'name' => '狂风',
- 'level' => 10
- ];
- }
- if ($speed > 102 && $speed <= 117) {
- $wind = [
- 'name' => '暴风',
- 'level' => 11
- ];
- }
- if ($speed > 117 && $speed <= 134) {
- $wind = [
- 'name' => '台风',
- 'level' => 12
- ];
- }
- if ($speed > 134 && $speed <= 149) {
- $wind = [
- 'name' => '台风',
- 'level' => 13
- ];
- }
- if ($speed > 149 && $speed <= 166) {
- $wind = [
- 'name' => '台风',
- 'level' => 14
- ];
- }
- if ($speed > 166 && $speed <= 183) {
- $wind = [
- 'name' => '台风',
- 'level' => 15
- ];
- }
- if ($speed > 183 && $speed <= 201) {
- $wind = [
- 'name' => '台风',
- 'level' => 16
- ];
- }
- if ($speed > 201 && $speed <= 220) {
- $wind = [
- 'name' => '台风',
- 'level' => 17
- ];
- }
- if ($speed > 220) {
- $wind = [
- 'name' => '台风',
- 'level' => 18
- ];
- }
- return $wind;
- }
- private function getSkycon($skycon)
- {
- $arr = [
- 'CLEAR_DAY' => '晴',
- 'CLEAR_NIGHT' => '晴',
- 'PARTLY_CLOUDY_DAY' => '多云',
- 'PARTLY_CLOUDY_NIGHT' => '多云',
- 'CLOUDY' => '阴',
- 'LIGHT_HAZE' => '轻度雾霾',
- 'MODERATE_HAZE' => '中度雾霾',
- 'HEAVY_HAZE' => '重度雾霾',
- 'LIGHT_RAIN' => '小雨',
- 'MODERATE_RAIN' => '中雨',
- 'HEAVY_RAIN' => '大雨',
- 'STORM_RAIN' => '暴雨',
- 'FOG' => '雾',
- 'LIGHT_SNOW' => '小雪',
- 'MODERATE_SNOW' => '中雪',
- 'HEAVY_SNOW' => '大雪',
- 'STORM_SNOW' => '暴雪',
- 'DUST' => '浮尘',
- 'SAND' => '沙尘',
- 'WIND' => '大风',
- 'SLEET' => '雨夹雪',
- 'THUNDER_SHOWER' => '雷阵雨',
- 'HAIL' => '冰雹',
- ];
- return $arr[$skycon] ?? "";
- }
- private function getAlert($code, $type = 1)
- {
- $alert_type = [
- '01' => '台风',
- '02' => '暴雨',
- '03' => '暴雪',
- '04' => '寒潮',
- '05' => '⼤风',
- '06' => '沙尘暴',
- '07' => '高温',
- '08' => '干旱',
- '09' => '雷电',
- '10' => '冰雹',
- '11' => '霜冻',
- '12' => '大雾',
- '13' => '霾',
- '14' => '道路结冰',
- '15' => '森林火灾',
- '16' => '雷雨大风',
- ];
- $alert_level = [
- '01' => '蓝色',
- '02' => '黄色',
- '03' => '橙色',
- '04' => '红色',
- ];
- $code_1 = substr($code, 0, 2);
- $code_2 = substr($code, 2, 2);
- if ($type == 1) {
- return $code ? $alert_type[$code_1] . $alert_level[$code_2] . '预警' : "";
- } else {
- return $alert_level[$code_2] ?? "";
- }
- }
- }
|