질문/조언질답게시판

우선 포인트자료인데 일부 소스를 공개해야 하는데 문제가 되면 추후 조치를 하겠습니다.

 

//날씨연동시 기상청 날씨정보 파싱 및 캐시저장
    if($addon_info->weather_kma == 'yes'){
        //캐싱설정
        $cache_path = './files/cache/snow_falling_addon/';
        FileHandler::makeDir($cache_path);
        $cache_name = 'snow_falling_addon';
        $cache_time = 60*60;    //캐시할 시간 (60분)
        $cache_file = sprintf('%s%s.cache', $cache_path, $cache_name);
    
        //캐시파일 있으면
        if(file_exists($cache_file)){
            //캐싱시간확인
            $filemtime = filemtime($cache_file)+$cache_time;
            $servertime = $_SERVER['REQUEST_TIME'];
            //캐싱시간인경우 캐시파일로드
            if($filemtime > $servertime){
                $cache_body = FileHandler::readFile($cache_file);
            }else{
                //캐싱시간 지난경우 캐시파일삭제
                FileHandler::removeFile($cache_file);
            }
        }
        //캐시파일 없으면 데이터 생성 및 캐시파일로 저장
        if(!file_exists($cache_file)){
            //날씨정보가공
            ini_set("allow_url_fopen","1");    //서버 fopen 허용
            $kma_url = "http://www.kma.go.kr/wid/queryDFS.jsp?gridx=67&gridy=108";    //어디기준 날씨정보인지 확실하지않음 ㅡㅡ;
            $xml = simplexml_load_file($kma_url); 
            //날짜데이터 시간
            $weather = sprintf('%d',$xml->header->tm);
            //가장 최근의 정보를 기준으로 정보저장
            if(count($xml->body->data) > 1){
                $weather .= sprintf(',%s',$xml->body->data[0]->wfKor);    //결과) 시간,날씨상태(맑음,구름조금,구름많음,흐림,비,눈/비,눈)
            }
            //가공된 정보 캐시정보에 넣음
            $cache_content = $weather;
            //캐시생성
            FileHandler::writeFile($cache_file, $cache_content);
            //캐시파일로드
            $cache_body = FileHandler::readFile($cache_file);
        }

 

 

 

현재 특정 지역을 특정하여 기상정보를 확인 후 해당 기상정보로 눈효과 여부를 결정하고 있습니다.

 

이를.... 접속하는 유저의 지역으로 해서 기상정보를 가져와 개개인마다 다르게 해 보려고합니다. 

 

 

 

캐시를 사용하지 않게 하고 쿠키를 사용하여 30분 정도마다 확인하게 하는게 어떨까 하는 생각을 했습니다.

 

http://smart-ip.net/geoip-api

여기서 위도와 경도를 구할 수 있습니다.

 

기상청에서는 x,y  좌표값을 사용하는데 위도,경도를 이 값으로 변환해주는 소스가 기상청에 있다고 하네요.

http://www.kma.go.kr/weather/forecast/digital_forecast.jsp

 

 

<!doctype html>
<html>
 <head>
  <meta charset="UTF-8"> 
  <title>Document</title>

  <style>
    textarea {width:350px; height:300px; float:left}
    .btnGroup {
        float:left ;
        padding: 25px;
    }
  </style>
  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script>

  
    // 위경도 -> GridXY
    function fnLatLon2XY() {
        var strLatLon = $.trim($("#taLatLon").val());
        if(!strLatLon) { alert("위경도 데이터를 입력하여 주십시오."); return;}
        var lines = strLatLon.split(String.fromCharCode(10)); //줄단위로 분할
        var strXY = "";
        for(var i = 0, len = lines.length; i < len; i++) {
            if(lines[i] == "") continue; //빈줄은 무시하고 통과
            var latlon = lines[i].split(",");
            var lat = latlon[0], lon = latlon[1];
            if(!lat||!lon||isNaN(lat)||isNaN(lon)) {
                alert("숫자 값이 아니거나 데이터 형식이 맞지 않습니다.");
                return;
            }
            var xy = dfs_xy_conv("toXY", lat, lon);
            strXY += xy.x + ", " + xy.y + String.fromCharCode(10);
        }
        
        $('#taXY').val(strXY);

    }
    // 위경도 <- GridXY
    function fnXY2LatLon() {

        var strXY = $.trim($("#taXY").val());
        if (! strXY) { alert ("Grid XY 데이터를 입력하여 주십시오."); return; }
  
        var lines = strXY.split(String.fromCharCode(10));
        var strLatLon = "";
        for(var i = 0, len = lines.length; i < len; i++) {
            if (lines[i] == '')  continue;       
    
            var xy = lines[i].split(",");
            var x = xy[0], y = xy[1];
            if (!x || !y || isNaN(x) || isNaN(y)) {
                alert("숫자 값이 아니거나 데이터 형식이 맞지 않습니다.");
                return;
            }
    
            var ll = dfs_xy_conv("toLL", x, y);
            strLatLon += ll.lat + ", " + ll.lng + String.fromCharCode(10);
    
        }  
        $("#taLatLon").val(strLatLon);
    }

    //----------------------------------------------------------
    // 기상청 홈페이지에서 발췌한 변환 함수
    //
    // LCC DFS 좌표변환을 위한 기초 자료
    //
    var RE = 6371.00877; // 지구 반경(km)
    var GRID = 5.0; // 격자 간격(km)
    var SLAT1 = 30.0; // 투영 위도1(degree)
    var SLAT2 = 60.0; // 투영 위도2(degree)
    var OLON = 126.0; // 기준점 경도(degree)
    var OLAT = 38.0; // 기준점 위도(degree)
    var XO = 43; // 기준점 X좌표(GRID)
    var YO = 136; // 기1준점 Y좌표(GRID)

// LCC DFS 좌표변환 ( code : 
//          "toXY"(위경도->좌표, v1:위도, v2:경도), 
//          "toLL"(좌표->위경도,v1:x, v2:y) )
//

    function dfs_xy_conv(code, v1, v2) {
        var DEGRAD = Math.PI / 180.0;
        var RADDEG = 180.0 / Math.PI;
        
        var re = RE / GRID;
        var slat1 = SLAT1 * DEGRAD;
        var slat2 = SLAT2 * DEGRAD;
        var olon = OLON * DEGRAD;
        var olat = OLAT * DEGRAD;
        
        var sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);
        sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);
        var sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
        sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
        var ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
        ro = re * sf / Math.pow(ro, sn);
        var rs = {};
        if (code == "toXY") {
            rs['lat'] = v1;
            rs['lng'] = v2;
            var ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5);
            ra = re * sf / Math.pow(ra, sn);
            var theta = v2 * DEGRAD - olon;
            if (theta > Math.PI) theta -= 2.0 * Math.PI;
            if (theta < -Math.PI) theta += 2.0 * Math.PI;
            theta *= sn;
            rs['x'] = Math.floor(ra * Math.sin(theta) + XO + 0.5);
            rs['y'] = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5);
        }
        else {
            rs['x'] = v1;
            rs['y'] = v2;
            var xn = v1 - XO;
            var yn = ro - v2 + YO;
            ra = Math.sqrt(xn * xn + yn * yn);
            if (sn < 0.0) - ra;
            var alat = Math.pow((re * sf / ra), (1.0 / sn));
            alat = 2.0 * Math.atan(alat) - Math.PI * 0.5;
            
            if (Math.abs(xn) <= 0.0) {
                theta = 0.0;
            }
            else {
                if (Math.abs(yn) <= 0.0) {
                    theta = Math.PI * 0.5;
                    if (xn < 0.0) - theta;
                }
                else theta = Math.atan2(xn, yn);
            }
            var alon = theta / sn + olon;
            rs['lat'] = alat * RADDEG;
            rs['lng'] = alon * RADDEG;
        }
        return rs;
    }

  </script>

 </head>
 <body>    
    <textarea id="taLatLon" >37.579871128849334, 126.98935225645432
35.101148844565955, 129.02478725562108
33.500946412305076, 126.54663058817043</textarea>
    <div class="btnGroup">
        <button onclick="fnLatLon2XY()">위경도 -> GridXY</button><br/><br/>
        <button onclick="fnXY2LatLon()">위경도 <- GridXY</button>
    </div>

    <textarea id="taXY"></textarea>
  
 </body>
</html>

 

 

https://javaking75.blog.me/220089575454

 

 

개발자분들은 쉽게 브라우저의 현위지 좌표를 가지고 가변적인 동네날씨 정보 주소를 가져오게 하실 수 있을 것 같아 한번 정보를 모아 질문을 드려봅니다.

 

눈송이 애드온 : https://xetown.com/rxe_point/96271

  • profile
    예전에 제가 공유한 소스인데 참고하시면 좋을 것 같아요

    https://xetown.com/rxe_file/104275
  • profile
    지역은 http://www.kma.go.kr/weather/lifenindustry/sevice_rss.jsp 여기서 찾으시면 됩니다.
  • profile profile
    클라이언트 아이피로 자동으로 지역주소를 결정해서 날씨정보를 가져오고 싶어서요.
  • profile profile
    기상청에서 가져오는건 이 소스를 애드온에서 사용했더라구요.
  • profile profile
    ip주소로 지역을 특정하려면 ~https://whois.kisa.or.kr/kor/whois/whois_.jsp?query=ip주소

    요기서 지역을 알아내야 할거에요 근데 갠적으로 비추에요~
  • profile profile
    본문에 아이피로 위도 경도 정보제공하는 곳 api 정보 적어 놓았습니다.
    위도 경도로 기상청 좌표값 변환하는 소스도 본문에 적어 놓았구요.
  • profile profile
    죄송 잘못봤네요.
  • profile
    본문의 ip로 위도경도 구하는 api가 잘 동작하지 않는거 같아서..   비영리 분당 150회
    http://ip-api.com/
  • profile
    새방식으로 질문글을 다시 올렸습니다.
    https://xetown.com/qna/833917