티스토리 뷰

2020-03-12 일 서버 소스의 작동속도가 조금더 향상되었습니다.

 

그간의 어플 히스토리
구글배포 -시작2015-06( blockmers 라는 패키지로 다른 구글 계정으로 런칭) - 사용자 100명
2018년  ( blockmers2 라는 패키지로 현재 구글 계정으로 런칭 ) - 사용자 100명
2020 코로나 사태 이후 사용자 10만명 직후 구글측의 정지처분
3월중 1차 구글 측의 어플 정지 처분 : 재난 상황을 이용해 돈을 버는 행위 금지 라는것
( 재난 상황을 악용해 돈을 버는걸 문제삼는 조항을 과도하게 해석한게 아닌지 
 재난 상황을 극복하려고 수익을 내는걸 차단하는건 아쉬운 부분임 )
어플 내부에 광고를 제거하고 2차 런칭 - 앱명 : 신코동비 (신종코로나 동선 비교)
구글측으로부터의 3월중 2차 정지 : 2020-03-16
국가기관이나 신뢰가 가는 의료 단체로부터의 어플 검증을 받아서 증빙문서를 구글측에 보내서 승인을 받아야 한다는 이유
( 구글측이 어플을 리버싱하여 무슨 불법적인 사항이 있는지 다 확인해 볼 수 있음에도 타단체에
전산적인 검증을 받아야 한다는것은 아쉬움이 있음. )

 

해외의 경우 확진자의 노출위치의 일시적 공개에 민감할 수 있어

구글 내부적인 사정에 의해 어플을 구글플레이에서 중단시킨걸로 생각되는 사항입니다.

 

위의 과정이 불필요한 대한민국 국내의 원스토어 에만 어플을 배포 하였습니다

 

 

참고(포브스) : https://www.forbes.com/sites/thomasbrewster/2020/03/24/google-bans-coronavirus-apps-but-after-400000-downloads/#3d83354534c0

 

Google Bans Coronavirus Infection Trackers... But Not Before They Get 400,000 Downloads

Google is culling its Play store of unofficial coronavirus apps, but they’d already scored at least 400,000 downloads.

www.forbes.com

히스토리 끝

 

 


현재 오직 한국의 원스토어에서만 배포중 (KOREA ONESTORE) :
https://www.onestore.co.kr/userpoc/apps/view?pid=0000746566

 

 

[ 내가 그 시점에 환자 근처에 있었는지 검사해줍니다.  ]

 

 

자신이 사는 곳에 대한 환자정보 서버를 구축하여 앱을 통해 사람들에게 자신이 수집한 환자정보를 공유하여

스스로 역학조사를 해보는 방법에 대해 공유합니다.

 

 

윈도우10 기준으로 설명드립니다. 

 

https://nodejs.org/ko/download/

에서 nodejs 윈도우 버전 64-bit Windows Installer (.msi ) 를 받으면 됩니다. 

 

받은 후 클릭하여 설치합니다.

 

 

이후 단축키 Ctrl + R ==> cmd 입력-> 엔터

로 도스 명령창을 실행합니다.

 

 mkdir c:\nodejs_server

cd c:\nodejs_server

npm install express

 

 

윈도우 탐색기에서 c:\nodejs_server 폴더에 들어가서  block_corona_server.js 파일을 만듭니다.  

파일을 저장시엔 에디트 플러스 같은 문서편집툴에서

다른이름으로 저장-> UTF-8 인코딩 방식을 지정해서 하시면 됩니다.

 

 

 

이후  block_corona_server.js 의 소스 내용입니다. 빨간 부분만 수정해서 사용하면 됩니다.


__________________________________________________

 

 

 

var express = require('express')
var app = express()
var fs = require('fs');
var path = require('path');
var qs = require('querystring');


//___________________________________________________
//환자정보 ()
//___________________________________________________

/*

주의 사항 :

1. get_in_time ,get_out_time 시간은 다르더라도 같은 일자로 설정바랍니다.

여러날짜에 걸쳐 등록시 동선을 일자별로 더 추가바랍니다.

2. check_radius 값은 감지거리로 50 이 최고입니다 ( 50은 50미터 입니다 )

*/


var staticdata = {
    "mersfirelist": [

       

      /*  환자 동선 한개 추가시 */

      
            "id": 101,
            "command":"merge",
            "visible":"show",
            "getinfo": "GPS",
            "latitude": 37.444792,
            "longitude": 126.453688,
            "get_in_time": "2018-09-07 16:51:00",
            "get_out_time": "2018-09-07 17:51:00",
            "check_radius": 50,
            "title": "제목",
            "content": "내용",
             "title_eng": "영문제목",
            "content_eng": "영문내용",
            "sicker_type": "경유",
            "address": "한글 주소",
            "refer_url": "http://www.hani.co.kr/arti/society/health/861324.html"
        }

 

        ,   /* 각 동선 구분 콤마 */

 

      /*  환자 동선 한개  삭제시*/

        {
            "id": 101,
            "command":"delete",   //delete 로 지정하여 이전 id가 101 인 건 삭제 되도록 함
            "visible":"",
            "getinfo": "",
            "latitude": 0.0,
            "longitude": 0.0,
            "get_in_time": "",
            "get_out_time": ",
            "check_radius": 0,
            "title": "",
            "content": "",
             "title_eng": "",
            "content_eng": "",
            "sicker_type": "",
            "address": "",
            "refer_url": ""

        },

        위의 내용 환자 동선 갯수만큼 콤마로 구분해서 추가하면 됩니다.


    ]
};


//_______________________________________________

 

 

 


//________________________________________________
//공지사항
//________________________________________________


var staticnotice = {
    "noticelist": [
   
  {"tit_content":"본인국가 공지사항 제목|공지내용|공지내용영문| 공지내용 영문"},
  {"tit_content":"본인국가 공지사항 제목2|공지내용2|공지내용영문2 | 공지내용 영문2"}

   //위의 내용 반복

   //...

   
     ]
};

//________________________________________________
 

 

 

 


//_______________________________________________
//이 아래 수정 불필요 그대로 쓰면됨
//_______________________________________________

 


//__________________________________________________
// 2020-03-12일 추가 
//__________________________________________________
function isEmpty(str){
 
if(typeof str == "undefined" || str == null || str == "")
return true;
else
return false ;
}

HashMap = function(){
this.map = new Array();
};

HashMap.prototype = {
put : function(key,value){
this.map[key] = value;
} ,
get:function(key){
return this.map[key];
} ,
clear: function(){
this.map = new Array();
}
};

var staticmap = null;

function map_init(){
if( staticmap == null){
staticmap = new HashMap();
for(i = 0 ;i < staticdata.mersfirelist.length ;i++){
if( isEmpty(staticmap.get( staticdata.mersfirelist[i].id ) ) ) {
staticmap.put( staticdata.mersfirelist[i].id  , i );
}
}
}
}
//__________________________________________________
//2020-03-12일 추가 끝
//__________________________________________________



app.get('/upload/notice.json', function(request, response){
    try{
        request.accepts('application/json');

        response.json(staticnotice);
       
   
    }catch(e){
        console.log(JSON.stringify(e));
    }
});



app.get('/upload/serverside.json', function(request, response){
    try{
        request.accepts('application/json');

 

        map_init();//2020-03-12 추가


        response.json(staticdata);
       
   
    }catch(e){
        console.log(JSON.stringify(e));
    }
});




app.get('/upload/serverside.json/:maxcurid', function(request, response){
    try{
    request.accepts('application/json');

 

    map_init();//2020-03-12 추가

    var filteredId = path.parse(request.params.maxcurid).base;
   
    var numparamid = Number(filteredId);
   
    var retstr = "";
    var isfirst = true;

    var new_item_find = false;

 

    //----------------------------------------------------------
    //2020-03-12 추가
    //----------------------------------------------------------
    var startidx = 0;
    if(staticmap!=null){
       if( !isEmpty(staticmap.get(filteredId)) ){
        startidx = staticmap.get(filteredId);
       }
    }
    //----------------------------------------------------------

 

 


    for(i = startidx ; i < staticdata.mersfirelist.length ;i++){
        var numid = Number(staticdata.mersfirelist[i].id );


        if(numid >= numparamid){
             new_item_find = true;
        }

        if( new_item_find ){
       
            if(isfirst){
                isfirst = false;
            }else{
                retstr += ",";
            }
            retstr += "{";
            retstr += "\"id\": "+numid +",";
            retstr += "\"command\":\""+staticdata.mersfirelist[i].command +"\",";
            retstr += "\"visible\":\""+staticdata.mersfirelist[i].visible +"\",";
            retstr += "    \"getinfo\": \""+staticdata.mersfirelist[i].getinfo +"\",";
            retstr += "    \"latitude\":"+staticdata.mersfirelist[i].latitude +",";
            retstr += "    \"longitude\": "+staticdata.mersfirelist[i].longitude +",";
            retstr += "    \"get_in_time\": \""+staticdata.mersfirelist[i].get_in_time +"\",";
            retstr += "    \"get_out_time\": \""+staticdata.mersfirelist[i].get_out_time +"\",";
            retstr += "    \"check_radius\":" +staticdata.mersfirelist[i].check_radius +",";
            retstr += "    \"title\": \""+staticdata.mersfirelist[i].title +"\", ";
            retstr += "    \"content\": \""+staticdata.mersfirelist[i].content +"\",";
            retstr += "    \"title_eng\": \""+staticdata.mersfirelist[i].title_eng +"\",";
            retstr += "    \"content_eng\": \""+staticdata.mersfirelist[i].content_eng +"\",";
            retstr += "    \"sicker_type\": \""+staticdata.mersfirelist[i].sicker_type +"\",";
            retstr += "    \"address\": \""+staticdata.mersfirelist[i].address +"\",";
            retstr += "    \"refer_url\": \""+staticdata.mersfirelist[i].refer_url +"\"";
            retstr += "    }";
        }
    }
   
    var allret = "";
    allret += "{";
    allret += "\"mersfirelist\": [";
    allret += retstr;
    allret += "]";
    allret += "};";


    response.send(allret);
    //response.json(staticdata);
   
   
    }catch(e){
        console.log(JSON.stringify(e));
    }
});

 
 
 
 
 
app.listen(1234, function() {
  console.log('Example app listening on port 1234!')
});

//_____________________________________________

 

 

 

 

 

 

 

 

________________________________________________

 

 

[서버 시작 방법]

CMD 명령창의 C:\nodejs_server 경로 내에서 아래를 실행하여 서버를 실행합니다.
node  --max-old-space-size=4096    block_corona_server.js

 

 

[서버 종료 방법]
서버종료시 CTRL+C 눌러서 종료할 수 있습니다.

 

 

[서버 정보 업데이트 후 재시작 방법]
환자정보 추가시 block_corona_server.js 파일내용에 환자정보를 추가하고
서버를 ctrl+c 를 눌러 종료후
node  --max-old-space-size=4096    block_corona_server.js
위의 문장을 실행시킨 후 명령창을 끄지 말고 켜둬야 서버가 계속 돌아갑니다.

 

 

[ 구축한 서버에 접속하는 방법 ]

서버피씨의 방화벽을 끕니다.

CTRL + R -> CMD 입력 -> 엔터 -> IPCONFIG -> 엔터

로 서버피씨의 IP를 알아낸 후

폰에서 서버PC와 동일한 모뎀장비로 와이파이 인터넷을 연결 한 후 모바일 인터넷 기능은 꺼둡니다.
앱에서 [기타] -> [서버설정]-> [사설 서버 IP(환자정보제공용)] 에  [서버 pc의 IP:1234] 또는 [도메인 주소:1234]

[추가] 버튼을 눌러 추가후 선택하여 [적용] 버튼을 누르면  

해당 서버의 환자정보를 받아볼 수 있습니다.

이 후 해당 서버가 제공하는 환자노출정보와 자신의 동선을 비교하여 검사하는게 가능하겠습니다.


 



 

[본인의 서버를 타인에게도 공개하는 방법]

내부아이피를 포트포워딩을 통해서 외부아이피로 연결시키고

서비스로 사용할 포트의 방화벽을 오픈하고
자신이 돌리는 서버의 url 이나 외부ip 주소를  각 국가,각 지자체, 각모임 별 또는 SNS 나 커뮤니티에 공유해서
다른사람이 내가 공개한 환자정보를 앱에서 보고 접촉기록이 있는지 확인해볼 수 있습니다.

또는 타인이 공개한 환자발생정보 서버에 접속하여 내 이동 동선과 검사하여 접촉기록이 있었는지  

확인해볼 수 있습니다. 

 

 

 

환자정보 하나에 해당하는 포맷을 다시 알려드립니다.

______________________________________________

command : beforedelete 나 beforehidden

..

content : '202' -->  202 이전의 아이디에 대해 모두 삭제하거나 안보이게함

content 에 '202' 처럼 아이디 값 입력시 그 이전의 아이디값들의 동선 정보가 각 앱사용자들의 폰에서 모두 삭제되거나 모두 보이지 않게 됩니다.

______________________________________________

______________________________________________

command : deleteone hiddenone

..

content : '211' --> 지우거나 안보이게할 아이디 지정

content 에 '211' 처럼 아이디 값 입력시 해당 아이디값의 동선 정보가 각 앱사용자들의 폰에서 모두 삭제되거나 모두 보이지 않게 됩니다.

______________________________________________

______________________________________________

command : bfdatedelete bfdatehidden

..

content : '2020-05-01 15:03:33' --> 이 값보다 이전 날짜동선을 모두 지우거나 안보이게 함

______________________________________________

--------------   환자정보 한개의 포맷  시작  ---------------

        {
            "id": 101,                                    -->식별자
        "command":"merge",  ---> merge 또는 delete 또는 beforedelete 또는 beforehidden
        "visible":"show",          --> show 로 고정
            "getinfo": "GPS",   ----> 수집 방법 : GPS 로 고정
            "latitude": 35.1792708,  --> 위도
        "longitude": 126.8198425,  ---> 경도
        "get_in_time": "2015-06-14 12:23:39",  ---->  해당위치에 들어간 시간
        "get_out_time": "2015-06-14 12:25:51", ----> 해당 위도 경도에서 나온시간
        "check_radius": 10, ---> 체크 반경 미터단위
        "title": "00에서 00발생",  --> 제목
        "content": "내용",  --> 내용
         "title_eng": "at 00 fire", --> 영문제목
        "content_eng": "abcdefg",  --> 영문 내용
        "sicker_type": "경유",     ----> 환자 타입 : 경유, 격리,등등
        "address": "서울시 xxx", ---> 주소
        "refer_url": "http://aaere.aa.com"  ---> 출처
    }


-----------------------------  환자정보 한개의 포맷   끝-----------------


-----------------------------  공지사항 한개의 포맷  시작  --------------

        {"tit_content":"제목|내용|eng제목|eng내용"}


-----------------------------  공지사항 한개의 포맷 끝  ----------------

 

 

 

진행하시다 궁금하신점이 있다면 댓글 남겨주시면 답변해드리겠습니다.

 

  

또한 위의 내용을 SNS 나 번역하여 해외 확진자들이 나오고있는 국가들에 공유 부탁드립니다.
 

 

문의 사항은 댓글이나

croozfactory@gmail.com 로 보내주시면 되겠습니다.