yuanhung yeh
2020-10-27 5b98e9857d5081c30fcef0206c38f384dc542514
add project file
1 files modified
14 files added
980 ■■■■■ changed files
Dockerfile 21 ●●●●● patch | view | raw | blame | history
README.md 4 ●●●● patch | view | raw | blame | history
app.py 120 ●●●●● patch | view | raw | blame | history
config.py 31 ●●●●● patch | view | raw | blame | history
ctls.py 80 ●●●●● patch | view | raw | blame | history
deployEnv/Dockerfile 16 ●●●●● patch | view | raw | blame | history
deployEnv/requirements.txt 38 ●●●●● patch | view | raw | blame | history
package.json 17 ●●●●● patch | view | raw | blame | history
parser.py 262 ●●●●● patch | view | raw | blame | history
pub/extactJSON.py 30 ●●●●● patch | view | raw | blame | history
pub/postgis.py 180 ●●●●● patch | view | raw | blame | history
pub/queryMoi.py 44 ●●●●● patch | view | raw | blame | history
pub/utils.py 94 ●●●●● patch | view | raw | blame | history
requirements.txt 38 ●●●●● patch | view | raw | blame | history
wsgi.py 5 ●●●●● patch | view | raw | blame | history
Dockerfile
New file
@@ -0,0 +1,21 @@
FROM python-env:flask
WORKDIR /app
ADD . /app
ENV PG_HOST=192.168.11.42
ENV PG_PORT=5115
ENV PG_DATABASE=pgDMMS
ENV PG_USER=postgres
ENV PG_PASS=simple000
ENV DB_SRS=3826
ENV HTTP_PROXY=
ENV HTTPS_PROXY=
VOLUME ['/app/logs']
EXPOSE 5000
#ENTRYPOINT ["gunicorn","-w","1","-b","0.0.0.0:5000","wsgi:app"]
ENTRYPOINT ["python3", "app.py"]
#CMD
README.md
@@ -1,4 +0,0 @@
## g3d
pgDMMSto3D
app.py
New file
@@ -0,0 +1,120 @@
import os
import requests
from config import StagingConfig as conf
from flask import Flask
from flask import request
from ctls import Db
from pub.utils import Coords
from pub.extactJSON import ParserMOI as moiParser
from pub.queryMoi import QueryElevation as moiEvApi
from pub.postgis import Dbconnect as gis3d
#from parser import FeatureTableParser
app = Flask(__name__)
#app.config.from_envvar('YOURAPPLICATION_SETTINGS')
#app.config.from_object(os.environ['APP_SETTINGS'])
app.config.from_object(conf)
dbConf={"host": os.environ.get("PG_HOST", '192.168.11.42'),
            "port": os.environ.get("PG_PORT", '5115'),
            "database": os.environ.get("PG_DATABASE",'pgDMMSNS'),
            "user": os.environ.get("PG_USER",'postgres'),
            "password": os.environ.get("PG_PASS",'simple000'),
            "default97": os.environ.get("DB_SRS",'3826')
    }
dbSRS=os.environ.get("DB_SRS",'3826')
#dbConf= { "host":"192.168.11.42" ,
#    "port":"5115",
#    "database":"pgDMMSNS",
#    "user":"postgres",
#    "password":"simple000"
#}
def printcol(col):
    print(col)
@app.route('/')
def hello():
    return '?1/2/'
@app.route('/testPostgis')
def testdb():
    gis3d.testSelect();
    return 'done'
@app.route('/resetEv/<string:tablename>')
def resetTableEv(tablename):
    print('running resetEv')
    colgeom= request.args.get('geom',default='geom')
    #poi=  Updateev0 (self.updDB)
    #gis3d.fetchTable(dbConf,
    #      poi.sql_sel() ,
    #      poi)
    procSetTableEv= Db(dbConf)
    procSetTableEv.resetTabelEv(tablename,dbSRS=dbSRS,srcgeom=colgeom,desgeom=colgeom)
    return 'done'
@app.route('/getEv/<string:tablename>')
def featureEvby84(tablename):
    limit= request.args.get('limit',default=100,type=int)
    colgeom= request.args.get('geom',default='geom')
    print('running getEv')
    print(request.query_string)
    procGetTableEv=Db(dbConf)
    procGetTableEv.getTableEv(tablename,limit=limit,dbSRS=dbSRS,srcgeom=colgeom,desgeom=colgeom)
    return 'table={}({}-{}),limit={}'.format(tablename,colgeom,dbSRS,(limit))
@app.route('/test') #/<string:name>')
def hello_name():
    proj= request.args.get('proj', default =3857 , type = int)
    print( "proj={}".format(proj))
    moiApi= moiEvApi()
    (result, urltext)= moiApi.test()
    if(result.status_code == requests.codes.ok):
         resultjs=moiParser.toJSON(result.text)
    return "testmoi={},\n url={}".format(resultjs,urltext)
@app.route('/transform')
def transformCoord():
    src_proj= request.args.get('src',default=3826,type=int)
    des_proj= request.args.get('des',default=4326,type=int)
    dx = request.args.get('x',default=0,type=float)
    dy = request.args.get('y',default=0,type=float)
    result=[]
    ret_json ={'message':'input format GET/POST ','src':3826,'des':4326,'x':0,'y':0}
    #print( src_proj,des_proj,dx,dy)
    trans=Coords()
    if(src_proj == 3826 and des_proj==4326):
         result= trans.crs_t97tow84(dx,dy)
         ret_json= {'x':result[0],'y':result[1],'srid':4326}
    if(src_proj == 4326 and des_proj==3826):
         result= trans.crs_w84tot97(dx,dy)
         ret_json= {'x':result[0],'y':result[1],'srid':3826}
    if(src_proj == des_proj):
         ret_json= {'x':dx,'y':dy,'srid':src_proj}
    return ret_json
if __name__ == '__main__':
    print (dbConf)
    moiapi=os.environ.get("MOI_API","TW_DLA_2001084_20061226_20M_3826_DEM")
    moikey=os.environ.get("MOI_KEY","43da4f4a-e2e0-43b0-a432-8b7975f43d9e")
    print('moikey=',moikey)
    print('moiapi=',moiapi)
    app.run(host='0.0.0.0',port=5000)
config.py
New file
@@ -0,0 +1,31 @@
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
    DEBUG = False
    TESTING = False
    CSRF_ENABLED = True
    SECRET_KEY = 'this-really-needs-to-be-changed'
#    dbConf={"host": os.environ["PG_HOST"],
#            "port": os.environ["PG_PORT"],
#            "database": os.environ["PG_DATABASE"],
#            "user": os.environ["PG_USER"],
#            "password": os.environ["PG_PASS"]
#    }
class ProductionConfig(Config):
    DEBUG = False
class StagingConfig(Config):
    DEVELOPMENT = True
    DEBUG = True
class DevelopmentConfig(Config):
    DEVELOPMENT = True
    DEBUG = True
class TestingConfig(Config):
    TESTING = True
ctls.py
New file
@@ -0,0 +1,80 @@
import datetime
from pub.extactJSON import ParserMOI as moiParser
from pub.queryMoi import QueryElevation as moiEvApi
from pub.postgis import Dbconnect
from parser import Updateev0
from parser import GetMoiEvBy84
class Db():
    def __init__(self,dbConf):
        self.dbConf=dbConf
        self.updateid=0
        self.dtStart=datetime.datetime.now()
        self.dtNext=datetime.datetime.now()
    def resetTabelEv(self,tablename,dbSRS='3826',srcgeom='geom',desgeom='geom'):
        #print (self.dbConf)
        self.gis3d= Dbconnect()
        print('setEv')
        self.gis3d.tryConn(self.dbConf)
        print('db ok')
        poi=  Updateev0 (tablename,self.updDB,dbSRS=dbSRS,srcgeom=srcgeom,desgeom=desgeom) #self.writeFile)
        #other connection
        self.gis3d.fetchTable( self.dbConf,
         poi.sql_sel() ,
         fnProc=poi
        )
        self.gis3d.destroyConn()
    def getTableEv(self,tablename,limit=100,dbSRS='3826',srcgeom='geom',desgeom='geom'):
        self.gis3d= Dbconnect()
        print('getEv')
        self.gis3d.tryConn(self.dbConf)
        print('db ok,limit={},srs={}'.format(limit,dbSRS))
        poi=  GetMoiEvBy84 (tablename,self.updDB,limit=limit,fnErr=self.writeFile,dbSRS=dbSRS,srcgeom=srcgeom,desgeom=desgeom) #self.writeFile) #self.updDB) #self.writeFile)
        #poi=  GetMoiEvBy84 (tablename,self.writeFile,limit=limit,fnErr=self.writeFile,dbSRS=dbSRS,srcgeom=srcgeom,desgeom=desgeom) #self.writeFile) #self.updDB) #self.writeFile)
        self.dtStart=datetime.datetime.now()
        #other connection
        self.gis3d.fetchTable( self.dbConf,
         poi.sql_sel() ,
         fnProc=poi
        )
        print ('total {}'.format(datetime.datetime.now()-self.dtStart))
        self.gis3d.destroyConn()
    def updDB(self,sql_upd,wkt,id,table):
        #print('update id',id)
        #self.updateid=self.updateid+1
        if(self.updateid % 100 == 0):
           dtnow= datetime.datetime.now()
           print('count:',self.updateid,'{}({})({} @ {})'.format(table,id,dtnow-self.dtNext, dtnow-self.dtStart))
           self.dtNext=datetime.datetime.now()
        self.updateid=self.updateid+1
        #print ('update!{}'.format(id,wkt))
        self.gis3d.executeWithConn(sql_upd.format(wkt,id))
#       #  print('nothing')
    def writeFile(self,sql_upd,wkt,id,table):
        #print('writefile',id)
        print(id)
        fname='logs/{}.{}.log'.format(table,self.dtStart.strftime('%Y%m%d_%H%M%S') )
        print ('error@({})-->{}'.format(id,fname ) )
        fp = open(fname, "a")
        lines =[sql_upd.format(wkt,id),";\n"]
        # ["One\n", "Two\n", "Three\n", "Four\n", "Five\n"]
        fp.writelines(lines)
        fp.close()
deployEnv/Dockerfile
New file
@@ -0,0 +1,16 @@
FROM python:3.8.5-buster
RUN apt update && apt-get install -y python3-setuptools
RUN apt install -y gdal-bin python3-gdal libgdal-dev
RUN python3 -m pip install Flask==1.1.1 --user &&  python3 -m pip install autoenv==1.0.0
RUN pip3 install --upgrade pip setuptools==45.2.0
RUN pip3 install numpy pyproj MarkupSafe python-dotenv psycopg2-binary
RUN pip3 install gdal==2.4.0
ADD requirements.txt .
RUN pip3 install -r requirements.txt
RUN pip3 install gunicorn
deployEnv/requirements.txt
New file
@@ -0,0 +1,38 @@
astroid==2.4.2
autoenv==1.0.0
certifi==2018.10.15
chardet==3.0.4
click==7.1.2
decorator==4.3.0
Flask==1.1.1
idna==2.7
ipython-genutils==0.2.0
isort==5.4.2
itsdangerous==1.1.0
Jinja2==2.11.2
jsonschema==2.6.0
jupyter-core==4.4.0
kafka-python==2.0.1
lazy-object-proxy==1.4.3
MarkupSafe==1.0
mccabe==0.6.1
nbformat==4.4.0
numpy==1.15.3
OWSLib==0.17.0
plotly==3.3.0
Pygments==2.2.0
pylint==2.6.0
pyproj==2.6.1
python-dateutil==2.7.5
pytz==2018.6
PyYAML==3.13
requests==2.20.0
retrying==1.3.3
Shapely==1.6.4.post2
six==1.15.0
toml==0.10.1
traitlets==4.3.2
typed-ast==1.4.1
urllib3==1.24
Werkzeug==1.0.1
wrapt==1.12.1
package.json
New file
@@ -0,0 +1,17 @@
{
  "name": "webapi",
  "version": "1.0.0",
  "description": "newbie",
  "main": "index.js",
  "scripts": {
    "initproj": "touch app/app.py .gitignore README.md requirements.txt",
    "install": "python3 -m pip install Flask==1.1.1 --user &&  python3 -m pip install autoenv==1.0.0",
    "pack": "python3 -m pip freeze > requirements.txt",
    "service":"gunicorn --bind 0.0.0.0:5000 wsgi:app",
    "docker": "docker build -t g3d .",
    "app": "python3 app.py",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
parser.py
New file
@@ -0,0 +1,262 @@
import requests
from pub.utils import Coords
from pub.utils import Geotext
from pub.queryMoi import QueryElevation #as httpMoi
from pub.extactJSON import ParserMOI as moiParser
class FeatureTableParser():
     def sql_sel(self):
         sqlWhere=''
         #gid >=1000 and gid <=5000
         if(len(self.where)):
            sqlWhere=' where {}'.format(self.where)
         sqlGid= (
      'select gid from '+
      '( select gid,count(*) numofPoint from ( '+
            ' select gid,(dp).path[2] SN,ST_Z((dp).geom) zpoint'+
            ' from (select gid,ST_DumpPoints({}) dp from {}."{}") allpoint '.format(self.geom,self.schema,self.table)+
         ') allzero {} group by gid '.format(sqlWhere)+
      ') numofzero {} '.format(self.limit) )
#            'select gid from ( '+
#            'select gid,count(*) numofPoint from ( '+
#            'select gid,ST_Z(ST_PointN( {}, generate_series(1, ST_NPoints({})))) zpoint '.format(self.geom,self.geom)+
#            ' from {}."{}"'.format(self.schema,self.table)+
#        ') allzero {} group by gid '.format(sqlWhere)+
#            ') numofzero {}'.format(self.limit) )
         sqlQuery=(
            'SELECT gid, did, tid, oid,gtype, pt,ST_X(geom3) x,ST_Y(geom3) y,ST_Z(geom3) z '+
            'from (   select gid,did,tid,oid,gtype,numpt, COALESCE((alldp).path[2],1) pt,(alldp).geom geom3 from ('+
            '   select gid,did,tid,oid ,GeometryType({}) gtype,ST_NPoints({}) numpt,'.format(self.geom,self.geom) +
            '   ST_DumpPoints({}) alldp from {}."{}"'.format(self.geom,self.schema,self.table)+
            ' ) atpoint where gid in ( {} )) allpt order by gid ,pt '.format(sqlGid))
#            'SELECT gid, did, tid, oid,gtype, pt,ST_X(geom3) x,ST_Y(geom3) y,ST_Z(geom3) z '+
#            ' from ( SELECT gid, did, tid, oid, GeometryType({}) gtype, '.format(self.geom) +
#            ' ST_NumPoints({})  , generate_series(1, ST_NPoints({})) pt, '.format(self.geom,self.geom)+
#            ' ST_PointN( {}, generate_series(1, ST_NPoints({}))) geom3 '.format(self.geom,self.geom)+
#            ' FROM {}."{}" where gid in ( '.format(self.schema,self.table)+
#            sqlGid+
#            ' )) allpt order by gid ,pt ')
         print(sqlQuery)
         return sqlQuery
         #(
         #'SELECT gid, did, tid, oid,gtype, pt,ST_X(geom3) x,ST_Y(geom3) y,ST_Z(geom3) z ' +
         #'from ( SELECT gid, did, tid, oid, GeometryType(geom) gtype, '+
         #'ST_NumPoints(geom)  , generate_series(1, ST_NPoints(geom)) pt, '+
         #'ST_PointN( geom, generate_series(1, ST_NPoints(geom))) geom3 '+
         #' FROM {}."{}" where gid in (select gid from {}."{}" {} ) ) allpt order by gid ,pt '.format(self.schema,self.table,self.schema,self.table,sqlwhere)  )
     def sql_upd(self,col_geom='geom'):
         return 'UPDATE {}."{}" set {}=ST_GeomFromEWKT(\'SRID={};{}\') where gid={}'.format(self.schema,self.table,col_geom,self.dbSRS,'{}','{}') #wkt,id)
     def colnames(self):
         return 'gid, did, tid, oid, gtype, pt, x, y, z'
     def colforgeotext(self,clos):
         return [(cols[0],cols[4],cols[5],cols[6],cols[7],cols[8])]
     def __init__(self,tablename,schema='gis3d',limit=100,where='zpoint=0',dbSRS='3826',geom='geom'):
         self.geom=geom
         self.schema=schema
         self.table=tablename
         self.where=where
         self.limit=''
         self.dbSRS=dbSRS
         if(limit>0):
             self.limit=' limit {}'.format(limit)
class Updateev0():
     def add(self,cols):
         self.geotext.add(cols[0],cols[4],cols[5],cols[6],cols[7],cols[8])
     #update DB
     def done(self,msg):
         self.geotext.done(msg)
     def updateto0(self,allpts):
         newpts=[];
         for onept in allpts:
             newpts.append([onept[0],onept[1],0])
         return newpts
     def upDb(self,pp4):
         #call ext
         #print(pp4[0],pp4[2])
         #print(pp4)
         if(self.fnAfter != None):
             self.fnAfter(self.sql_upd(), self.buildWKT(pp4[1],pp4[2]),pp4[0],self.table)
     def buildWKT(self,gtype,wktpt):
         resultwkt=''
         if(gtype=='POINT'):
             resultwkt='POINT({})'.format(wktpt)
         if(gtype=='POLYGON'):
             resultwkt='POLYGON(({}))'.format(wktpt)
         if(gtype=='LINESTRING'):
             resultwkt='LINESTRING({})'.format(wktpt)
         return resultwkt
     def sql_sel(self):
         return self.ft.sql_sel()
     def sql_upd(self):
         return self.ft.sql_upd(self.desgeom)
     def __init__(self,tablename,fnAfter=None,fnErr=None,limit=100,dbSRS='3826',desgeom='geom',srcgeom='geom'):
         print('init')
         self.table=tablename
         self.fnAfter=fnAfter
         self.fnErr=fnErr
         self.geotext=Geotext(self.updateto0,self.upDb)
         self.ft=FeatureTableParser(tablename,limit=limit,dbSRS=dbSRS,geom=srcgeom)
         self.desgeom=desgeom
class GetMoiEvBy84():
     def add(self,cols):
         self.geotext.add(cols[0],cols[4],cols[5],cols[6],cols[7],cols[8])
     #updatedb
     def done(self,msg):
         self.geotext.done(msg)
     #querybyimoi
     def procmoi(self,allpts):
         newpts=[];
         #print('coming',allpts)
         for onept in allpts:
             if(len(onept)>2):
                    newpts.append(self.towgs84(onept[0],onept[1],onept[2]))
             else:
                    if(self.fnErr!=None):
                         resultTxt='moi->{}  / {}'.format(onept,allpts)
                         self.fnErr('[error] {}, id->{}',resultTxt,'?','moi')
                    print('error@moi@{},row={}'.format(onept,allpts) )
         #print(self.makempoint(newpts))
         return newpts
     #parsertoWgs84
     def towgs84(self,dx,dy,dz):
         return self.coords.crs_t97tow84(dx,dy,dz)
     def makempoint(self,allpts):
         resultText='MULTIPOINT(({}))'
         resultOne=''
         for onept in allpts:
             if ( len(resultOne)>0):
                  resultOne+=','
             resultOne+= ' '.join ('%s' %id for id in onept)
         return resultText.format(resultOne)
     def printit(self,pp4):
         print(pp4)
     def queryBy(self,pp4):
         #queryMoi
         result=self.httpMoi.fromMoi("MULTIPOINT({})".format(pp4[2]))
         if(result.status_code == requests.codes.ok):
             resultjs=moiParser.toJSON(result.text)
             resultmoiarray=moiParser.moiJsonToArray(resultjs)
             #print('moi=',resultmoiarray)
             #print('org=',pp4)
             if (len(resultmoiarray)==0):
                    if(self.fnErr!=None):
                         resultTxt='moi->{},our->{}'.format(resultjs,'gid:{},to84:({}),from97:({})'.format(pp4[0],pp4[2], pp4[3]))
                         self.fnErr('[error] {}, id->{}',resultTxt,pp4[0],self.table)
                    print('error@parser@{},id={}'.format(self.table,pp4[0]) )
                    return
             if (self.fnAfter != None):
                    self.fnAfter(self.sql_upd(),
                         self.buildWKT(  pp4[1], self.makeSqlWktWithEv(pp4[3],resultmoiarray)) , pp4[0 ],self.table)
     def checkDistinctSquare(self,x0,y0,x1,y1):
         return (x0-x1)*(x0-x1)+(y0-y1)*(y0-y1)
     def makeSqlWktWithEv(self,xyorg,xymoi):
         lenOfxyorg=len(xyorg)
         #print('len',lenOfxyorg)
         newPts=[]
         for idxPt in range(lenOfxyorg):
             diff= self.checkDistinctSquare(
                    float(xyorg[idxPt][0]),float(xyorg[idxPt][1]),
                    float(xymoi[idxPt][0]),float(xymoi[idxPt][1]))
             if(diff>1):
                    print( 'diff xy({}> 1m)'.format( diff ))
             newPts.append([xyorg[idxPt][0],xyorg[idxPt][1],xymoi[idxPt][2]])
         resultText=''
         for pt in newPts:
             if(len(resultText)>0):
                 resultText+=','
             thisrow= ' '.join ('%s' %id for id in pt)
             resultText+= thisrow
         #print('wkt->',resultText)
         return (resultText)
     def upDb(self,pp4):
         #call ext
         #print(pp4[0],pp4[2])
         if(self.fnAfter != None):
             self.fnAfter(self.sql_upd(), self.buildWKT(pp4[1],pp4[2]),pp4[0])
     def buildWKT(self,gtype,wktpt):
         resultwkt=''
         if(gtype=='POINT'):
             resultwkt='POINTZ({})'.format(wktpt)
         if(gtype=='POLYGON'):
             resultwkt='POLYGONZ(({}))'.format(wktpt)
         if(gtype=='LINESTRING'):
             resultwkt='LINESTRINGZ({})'.format(wktpt)
         return resultwkt
     def sql_sel(self):
         return self.ft.sql_sel()
     def sql_upd(self):
         return self.ft.sql_upd(self.desgeom)
     def __init__(self,tablename,fnAfter=None,fnErr=None,limit=100,dbSRS='3826',desgeom='geom',srcgeom='geom'):
         print('init')
         self.coords=Coords(default97=dbSRS)
         self.httpMoi=QueryElevation()
         #
         self.geotext=Geotext(self.procmoi,self.queryBy)
         self.table=tablename
         self.fnAfter=fnAfter
         self.fnErr=fnErr
         self.ft=FeatureTableParser(tablename,limit=limit,dbSRS=dbSRS,geom=srcgeom)
         self.desgeom=desgeom
pub/extactJSON.py
New file
@@ -0,0 +1,30 @@
import xml.etree.ElementTree as ET
import json
class ParserMOI:
      """ A funny format convert """
      def findbyelement():
          return './string'
      def toJSON(xmlFromAPI):
          xmlelm= ET.fromstring(xmlFromAPI)
          #print('-------')
          #print(xmlelm)
          #print('->->')
          result=xmlelm
          #print(result.text)
          return json.loads(result.text)
      # ss='{"count": "2", "pointArray": [{"x": "300431.466453", "y": "2765416.019419", "z": "13.650453"}, {"x": "300428.019514", "y": "2765415.408211", "z": "13.498476"}]}'
      def moiJsonToArray(moijson):
          resultArray=[]
          if 'pointArray' not in moijson:
              print('error!',moijson)
              return []
          allxyz=moijson.get('pointArray')
          for row in allxyz:
              resultArray.append([row['x'],row['y'],row['z']])
          return resultArray
pub/postgis.py
New file
@@ -0,0 +1,180 @@
import psycopg2
class Dbconnect():
      def testSelect(self):
          conn = psycopg2.connect(host='192.168.11.42',port='5115',database='pgDMMSNS', user='postgres',password='simple000')
          print('connected')
#SELECT gid, did, tid, oid, cid, lid, level, symcolor, symweight, symstyle, geom FROM gis3d."fsc-401-c-0";
          cursor = conn.cursor()
          cursor.execute('SELECT gid, did, tid, oid, geom FROM gis3d."fsc-401-c-0"')
          rows =cursor.fetchall()
          for row in rows:
              print ('id=',row[0], ',gid=',row[1],',tid=',row[2],',oid=',row[3],'\n')
          cursor.close()
          conn.close()
      #select must offline
      def fetchTableWithConn(self,dbQuery,fnProc=None):
          arrayRow=[]
          try:
             cursor = self.dbConn.cursor()
             cursor.execute(dbQuery)
             rows = cursor.fetchall()
             arrayRow=rows
             #for row in rows:
             #     #print(row)
             #     #print(fnProc)
             #     if(fnProc!=None):
             #         if(fnProc.add !=None):
             #             fnProc.add( (row) )
          except(Exception, psycopg2.Error) as error:
             print("error connect",error)
             #conn =None
          finally:
             #if(fnProc!=None):
             #    if(fnProc.done !=None):
             #        fnProc.done( (dbQuery) )
             cursor.close()
             #read it
          print('close cursor')
          for row in arrayRow:
             if(fnProc!=None):
                  if(fnProc.add != None):
                       fnProc.add ( (row) )
                  lastrw=row
          if(fnProc !=None):
             if(fnProc.done != None):
                  fnProc.done({'sql':dbQuery,'row':lastrw} )
      def fetchTable(self,dbConf,dbQuery,fnProc=None):
          print('try database')
          #print('sqlis->',dbQuery)
          try:
             conn = psycopg2.connect(
                 host=dbConf['host'],
                 port=dbConf['port'],
                 database=dbConf['database'],
                 user=dbConf['user'],
                 password=dbConf['password']
             )
             cursor = conn.cursor()
             cursor.execute(dbQuery)
             rows = cursor.fetchall()
             lastrw={}
             for row in rows:
                 #print(row)
                 #print(fnProc)
                 if(fnProc!=None):
                     if(fnProc.add !=None):
                         fnProc.add( (row) )
                 lastrw=row
          except(Exception, psycopg2.Error) as error:
             print("error connect",error)
             conn =None
          finally:
             if(fnProc!=None):
                 if(fnProc.done !=None):
                     fnProc.done( ({'sql':dbQuery,'row':lastrw}) )
             if( conn != None):
                 cursor.close()
                 conn.close()
      def executeWithConn(self,dbSql,fnProc=None):
          try:
             cursor = self.dbConn.cursor()
             cursor.execute(dbSql)
             #record = cursor.fetchone()
             if(fnProc!=None):
                 if(fnProc.add !=None):
                     fnProc.add ( {} )
             #self.dbConn.commit()
          except(Exception, psycopg2.Error) as error:
             print("error connect",error,dbSql)
          finally:
             if(fnProc!=None):
                 if(fnProc.done !=None):
                     fnProc.done( (dbSql) )
             cursor.close()
      def execute(self,dbConf,dbSql,fnProc=None):
          print('try exec-database')
          #print('sqlis->',dbQuery)
          try:
             conn = psycopg2.connect(
                 host=dbConf['host'],
                 port=dbConf['port'],
                 database=dbConf['database'],
                 user=dbConf['user'],
                 password=dbConf['password']
             )
             cursor = conn.cursor()
             cursor.execute(dbSql)
             #record = cursor.fetchone()
             if(fnProc!=None):
                 if(fnProc.add !=None):
                     fnProc.add ( {} )
             conn.commit()
             print('commit')
          except(Exception, psycopg2.Error) as error:
             print("error connect",error)
             conn =None
          finally:
             if(fnProc!=None):
                 if(fnProc.done !=None):
                     fnProc.done( (dbSql) )
             if( conn != None):
                 cursor.close()
                 conn.close()
      def tryConn(self, dbConf):
          print('try database')
          print(dbConf)
          print(self)
          try:
             if (self.dbConn != None):
                 self.destroyConn()
             self.dbConn = psycopg2.connect(
                 host=dbConf['host'],
                 port=dbConf['port'],
                 database=dbConf['database'],
                 user=dbConf['user'],
                 password=dbConf['password'],
             )
             self.dbConn.set_session(autocommit=True)
          except(Exception, psycopg2.Error) as error:
             print("error connect",error)
             self.dbConn=None
      def destroyConn(self):
          try:
             if( self.dbConn != None):
                self.dbConn.close()
          except(Exception, psycopg2.Error) as error:
             print('close connect')
          finally:
             self.dbConn = None
      def __init__(self):
          self.dbConn=None
pub/queryMoi.py
New file
@@ -0,0 +1,44 @@
import os
import requests
class QueryElevation():
#      urlPattern='https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey=&wkt=MULTIPOINT(121.54%2024.44,121.54%2024.43,121.541%2024.43)&data=TW_DLA_20010814_20061226_20M_3826_DEM'
      def test(self):
          moitest='https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey=&wkt=MULTIPOINT(121.54%2024.44,121.54%2024.43,121.541%2024.43)&data=TW_DLA_20010814_20061226_20M_3826_DEM'
          #s=requests.get(moitest)
          proxy=self.getProxy()
          if (proxy == None):
             s= requests.get(moitest)
          else:
             s= requires.get(moitest,proxies=proxy)
          return (s , moitest)
      def fromMoi(self,wkt):
          #print('getwkt',wkt)
          urlExec=self.urlPattern.format(self.moi_key,wkt,self.moi_api)
          #print('url:',urlExec)
          proxy=self.getProxy()
          if (proxy == None):
             s= requests.get(urlExec)
          else:
             s= requests.get(urlExec,proxies=proxy)
          return s
      def getProxy(self):
          if (len(self.httpproxy)+len(self.httpsproxy)>0):
             return {"http":self.httpproxy,"https":self.httpsproxy}
          return None
      def __init__(self):
          self.httpproxy=os.environ.get("HTTP_PROXY","")
          self.httpsproxy=os.environ.get("HTTPS_PROXY","")
          self.moi_api=os.environ.get("MOI_API","TW_DLA_2001084_20061226_20M_3826_DEM")
          self.moi_key=os.environ.get("MOI_KEY","43da4f4a-e2e0-43b0-a432-8b7975f43d9e")
          #https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey=43da4f4a-e2e0-43b0-a432-8b7975f43d9e&wkt=MULTIPOINT((121.58364097028957 25.010770192742356))&data=TW_DLA_20110101_20161101_1M_3826_DEM
          self.urlPattern='https://dtm.moi.gov.tw/services/polate/polate.asmx/getPolate?apikey={}&wkt={}&data={}'
#TW_DLA_2001084_20061226_20M_3826_DEM'
pub/utils.py
New file
@@ -0,0 +1,94 @@
import datetime
from pyproj.crs import CRS
from pyproj import Transformer
#wgs84=CRS.from_epsg(4326)
#twd97=CRS.from_epsg(3826)
#trans97to84=Transformer.from_crs(twd97,wgs84)
#trans84to97=Transformer.from_crs(wgs84,twd97)
class Coords():
     def crs_t97tow84(self,dx,dy,dz=0,in3d=False):
         xyz= self.trans97to84.transform(dx,dy)
         if( in3d ):
           return [xyz[1] ,xyz[0],dz]
         return [xyz[1] ,xyz[0]]
     def crs_w84tot97(self,dx,dy,dz=0,in3d=False):
         xyz=  self.trans84to97.transform(dy,dx)
         if( in3d ):
           return [xyz[0] ,xyz[1],dz]
         return [xyz[0] ,xyz[1]]
     def __init__(self,default97='3826'):
         self.wgs84=CRS.from_epsg(4326)
         self.twd97=CRS.from_epsg(int(default97))
         self.trans97to84=Transformer.from_crs(self.twd97,self.wgs84)
         self.trans84to97=Transformer.from_crs(self.wgs84,self.twd97)
class Geotext():
     def add(self,id,gtype,sn,dx,dy,dz):
         #print(id,':',sn)
         #print(dx,dy,dz)
         if(id != self.id):
            if(self.sn !=0):
               self.done()
         self.id=id
         self.gtype=gtype
         self.sn=sn
         if(len(self.points)>=sn ):
            print('something wrong!!! sn < point!({})'.format(id))
         self.points.append([dx,dy,dz])
         self.dtStart=datetime.datetime.now()
     def clearpoint(self):
         self.id=''
         self.gtype=''
         self.points.clear()
         self.org.clear()
     def done(self,msg={}):
         self.org=self.points
         if (self.fnReady !=None):
            self.points=self.fnReady(self.points)
         #print(self.makewkt())
         #print('id={}'.format(self.id))
         if (self.fnNext !=None):
            self.fnNext(self.makewktpt())
         print('id={},({})'.format(self.id,datetime.datetime.now()-self.dtStart))
         if(len(self.points) != self.sn):
            print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            print(msg)
         self.sn=0
         self.points.clear()
         self.org.clear()
     def makewktpt(self):
         resultText=''
         for pt in self.points:
             if(len(resultText)>0):
                 resultText+=','
             thisrow= ' '.join ('%s' %id for id in pt)
             resultText+= thisrow
         #print('wkt->',resultText)
         return (self.id,self.gtype,resultText,self.org)
     def __init__(self,fnReady=None,fnNext=None):
         print('try init')
         self.gtype=''
         self.points=[]
         self.org=[]
         self.id=''
         self.sn=0
         self.fnNext=fnNext
         self.fnReady=fnReady
         self.dtStart=datetime.datetime.now()
requirements.txt
New file
@@ -0,0 +1,38 @@
astroid==2.4.2
autoenv==1.0.0
certifi==2018.10.15
chardet==3.0.4
click==7.1.2
decorator==4.3.0
Flask==1.1.1
idna==2.7
ipython-genutils==0.2.0
isort==5.4.2
itsdangerous==1.1.0
Jinja2==2.11.2
jsonschema==2.6.0
jupyter-core==4.4.0
kafka-python==2.0.1
lazy-object-proxy==1.4.3
MarkupSafe==1.0
mccabe==0.6.1
nbformat==4.4.0
numpy==1.15.3
OWSLib==0.17.0
plotly==3.3.0
Pygments==2.2.0
pylint==2.6.0
pyproj==2.6.1
python-dateutil==2.7.5
pytz==2018.6
PyYAML==3.13
requests==2.20.0
retrying==1.3.3
Shapely==1.6.4.post2
six==1.15.0
toml==0.10.1
traitlets==4.3.2
typed-ast==1.4.1
urllib3==1.24
Werkzeug==1.0.1
wrapt==1.12.1
wsgi.py
New file
@@ -0,0 +1,5 @@
from app import app
if __name__ == '__main__':
    app.run()