• 로그인
  • 장바구니에 상품이 없습니다.

home2 게시판 Node.js, Express 게시판 선생님의 도움이 필요합니다! node.js 와 python (flask)

선생님의 도움이 필요합니다! node.js 와 python (flask)

2 글 보임 - 1 에서 2 까지 (총 2 중에서)
  • 글쓴이
  • #85752

    정윤식
    참가자
    현재 python과 node.js의 서버 server.js 를 사용하여 mongoDB에 데이터를 저장하려고 합니다.
    <geo.py (public 디렉토리에 위치)>
    import json
    import os
    from flask import Flask, render_template, request, jsonify
    from pymongo import MongoClient
    import numpy as np
    from sklearn.linear_model import LinearRegression
    app = Flask(__name__, static_folder='public')
    client = MongoClient('mongodb://localhost:5000/')
    db = client['mapdata']  # 데이터베이스 이름 설정
    collection = db['calculate']  # 컬렉션 이름 설정
    @app.route("/")
    def index():
        return render_template("geo.ejs")
    @app.route("/geojson")
    def get_geojson():
        # file_path = os.path.join("public", "data.geojson")
        file_path = os.path.join(os.path.dirname(__file__), "public", "data.geojson")
        with open(file_path) as f:
            geojson_data = json.load(f)
        return jsonify(geojson_data)
    @app.route("/elevation", methods=["POST"])
    def calculate_elevation():
        data = request.get_json()
        coordinates = data.get("coordinates")
        # TODO: 좌표를 기반으로 고도 계산하기
        # elevations = []
        elevations = [100, 200, 300]
        file_path = os.path.join("public", "data.geojson")
        with open(file_path) as f:
            geojson_data = json.load(f)
        features = geojson_data["features"]
        for coord in coordinates:
            lat = coord[0]
            lon = coord[1]
            elevation = get_elevation_from_geojson(features, lat, lon)
            elevations.append(elevation)
        return jsonify(elevations)
    def get_elevation_from_geojson(features, lat, lon):
        for feature in features:
            coordinates = feature["geometry"]["coordinates"][0]  # 인덱스 수정
            if is_close(coordinates[0], lon) and is_close(coordinates[1], lat):
                return feature["properties"]["elevation"]
        return 0
    def is_close(a, b, rel_tol=1e-09, abs_tol=0.0):
        return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
    @app.route("/predict", methods=["POST"])
    def predict():
        data = request.get_json()
        elevations = data.get("elevation")
        # 경사도와 5분 동안의 심박수 증가량 데이터
        X = np.array(elevations)  # Elevation of trail 데이터
        Y = 10.2025 * np.power(X, 0.4392)  # 5분 동안의 심박수 증가량 데이터
        # 모델 훈련
        model = LinearRegression()
        X = X.reshape(-1, 1)  # 입력 데이터를 2D 배열로 변환
        model.fit(X, Y)
        # 모델 예측
        new_X = np.array(elevations)  # 예측을 위한 새로운 Elevation of trail 데이터
        new_X = new_X.reshape(-1, 1)  # 입력 데이터를 2D 배열로 변환
        predicted_Y = model.predict(new_X)
        return jsonify(predicted_Y.tolist())
    @app.route("/calculate_time", methods=["POST"])
    def calculate_time():
        data = request.get_json()
        from_latlng = data.get("from")
        to_latlng = data.get("to")
        increment_hr = data.get("Increment of HR")
        avg_hr = data.get("average HR")
        time_min = data.get("Taking Time(Minute)")
        if from_latlng is None or to_latlng is None:
            return jsonify("Start and end locations are required"), 400
        if avg_hr is None:
            return jsonify("Average HR is required"), 400
        predicted_time = (avg_hr - float(from_latlng["lat"])) / increment_hr * time_min
        if predicted_time < 20:
            return jsonify(0)
        # MongoDB에 데이터 저장
        route_data = {
            "from": from_latlng,
            "to": to_latlng,
            "increment_hr": increment_hr,
            "average_hr": avg_hr,
            "taking_time_min": time_min
        }
        collection.insert_one(route_data)
        response_data = {
            'result': '계산 결과',
        }
        return jsonify(response_data)
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=5000)
     
    <server.js 코드>
    
    
    
    const express = require('express')
    const app = express()
    var path = require('path');
    const http = require('http').createServer(app);
    // const {Server} = require('socket.io');
    // const io = new Server(http);
    const axios = require("axios");
    const { spawn } = require('child_process');
    const MongoClient = require('mongodb').MongoClient;
    const methodOverride = require('method-override')
    // const geoPyHost = 'localhost';
    // const geoPyPort = 5000;
    const serverPort = 8000;
    app.use(express.urlencoded({ extended: true }));
    app.use(methodOverride('_method'))
    app.set('view engine', 'ejs');
    app.use('/public', express.static('public'));
    const url = 'http://localhost:5000/calculate_time';
    const data = {
      from: { lat: 37.123, lng: 127.456 },
      to: { lat: 37.789, lng: 128.123 },
      'Increment of HR': 5,
      'average HR': 120,
      'Taking Time(Minute)': 30
    };
    axios.post(url, data)
      .then(response => {
        // 요청 성공 시 실행할 코드
        console.log(response.data);
      })
      .catch(error => {
        // 요청 실패 시 실행할 코드
        console.error(error);
      });
    var db;
    MongoClient.connect('mongodb+srv://@cluster0.ofcyns9.mongodb.net/mapdata?retryWrites=true&w=majority', function(에러, client) {
      db = client.db('mapdata');
      app.get('/', function (요청, 응답) {
        응답.render('index.ejs');
      });
      app.get('/write', function(요청, 응답) {
        응답.render('write.ejs');
      });
     
    //   app.listen(5000, function () {
    //     console.log('listening on 5000')
    //   });
    // })
    app.get('/list', function(요청, 응답) {
      
      db.collection('post').find().toArray(function(에러, 결과) {
        console.log(결과);
        응답.render('list.ejs', { posts : 결과 });
      });
       
    });
    app.get('/detail/:id', function(요청, 응답) {
      db.collection('post').findOne({_id : parseInt(요청.params.id)}, function(에러, 결과) {
        console.log(결과);
        응답.render('detail.ejs', { data : 결과 });
      });
    });
    app.get('/edit/:id', function(요청, 응답) {
      db.collection('post').findOne({_id : parseInt(요청.params.id)}, function(에러, 결과) {
      응답.render('edit.ejs', { post : 결과 })
      });
    });
    app.put('/edit', function(요청, 응답) {
      db.collection('post').updateOne({ _id : parseInt(요청.body.id)},{ $set : { 제목 : 요청.body.title, 날짜 : 요청.body.password}}, function(에러, 결과) {
        console.log('수정완료')
        응답.redirect('/list')
      })
    });
    const passport = require('passport');
    const LocalStrategy = require('passport-local').Strategy;
    const session = require('express-session');
    app.use(session({secret : '비밀코드', resave : true, saveUninitialized: false}));
    app.use(passport.initialize());
    app.use(passport.session());
    app.get('/login', function(요청, 응답) {
      응답.render('login.ejs')
    });
    app.post('/login', passport.authenticate('local', {
      failureRedirect : '/fail'
    }), function(요청, 응답) {
      응답.redirect('/')
    });
    app.get('/mypage', 로그인, function(요청, 응답) {
      console.log(요청.user);
      응답.render('geo.ejs', {사용자 : 요청.user})
    })
    function 로그인(요청, 응답, next) {
      if (요청.user) { 
        next() 
      } 
      else { 
        응답.send('You have to Log on.') 
      } 
    }
    passport.use(new LocalStrategy({
      usernameField: 'id',
      passwordField: 'pw',
      session: true,
      passReqToCallback: false,
    }, function (입력한아이디, 입력한비번, done) {
      //console.log(입력한아이디, 입력한비번);
      db.collection('login').findOne({ id: 입력한아이디 }, function (에러, 결과) {
        if (에러) return done(에러)
        if (!결과) return done(null, false, { message: '존재하지않는 아이디요' })
        if (입력한비번 == 결과.pw) {
          return done(null, 결과)
        } else {
          return done(null, false, { message: '비번틀렸어요' })
        }
      })
    }));
    passport.serializeUser(function (user, done) {
      done(null, user.id)
    });
    passport.deserializeUser(function (아이디, done) {
      db.collection('login').findOne({id : 아이디}, function(에러, 결과) {
        done(null, 결과)
      })
      
    });
    app.post('/register', function(요청,응답){
      db.collection('login').insertOne( {id : 요청.body.id, pw : 요청.body.pw}, function(에러, 결과) {
        응답.redirect('/')
      })
    });
    
    
    app.post('/add', function (요청, 응답) {
        
      응답.send('전송완료');
      db.collection('counter').findOne({name : '게시물갯수'}, function(에러, 결과) {
        console.log(결과.totalPost)
        var 총게시물갯수 = 결과.totalPost;
        var 저장할거 = {_id : 총게시물갯수 + 1, 작성자 : 요청.user._id, 제목 : 요청.body.title, 날짜 : 요청.body.password}
        db.collection('post').insertOne(저장할거 , function(에러, 결과) {
          console.log('저장완료');
          db.collection('counter').updateOne({name:'게시물갯수'}, { $inc : {totalPost:1} }, function(에러, 결과) {
            if(에러) {
              return console.log(에러)
            }
          })
        });
      });
      
    });
    app.delete('/delete', function(요청, 응답){
      console.log(요청.body);
      요청.body._id = parseInt(요청.body._id);
      var 삭제할데이터 = { _id : 요청.body._id, 작성자 : 요청.user._id }
      db.collection('post').deleteOne(삭제할데이터, function(에러, 결과) {
        console.log('삭제완료');
        if (에러) {console.log(에러)}
        응답.status(200).send({ message: '성공했습니다' });
      })
    });
    app.post('/calculate_time', function (req, res) {
      // 예상 시간 계산 로직
      const { from, to, 'Increment of HR': increment_hr, 'average HR': average_hr, 'Taking Time(Minute)': taking_time_min } = req.body;
      // 요청을 geo.py에 전달하여 예상 시간 계산
      // const pythonProcess = spawn('python', ['geo.py', JSON.stringify(from), JSON.stringify(to), increment_hr, average_hr, taking_time_min]);
      const pythonProcess = spawn('python', [path.join(__dirname, 'public/geo.py'), JSON.stringify(from), JSON.stringify(to), increment_hr, average_hr, taking_time_min]);
      pythonProcess.stdout.on('data', (data) => {
        const predictedTime = data.toString().trim();
        res.json(predictedTime);
        // 예상 시간을 MongoDB에 저장
        db.collection('calculate').insertOne({
          from: from,
          to: to,
          increment_hr: increment_hr,
          average_hr: average_hr,
          taking_time_min: taking_time_min,
          predicted_time: predictedTime
        }, function (에러, 결과) {
          if (에러) {
            return console.log(에러);
          }
          console.log('저장 완료');
        });
      });
      pythonProcess.stderr.on('data', (data) => {
        console.error(`stderr: ${data}`);
        res.status(500).json('An error occurred');
      });
    });
    app.listen(serverPort, () => {
      console.log(`서버가 ${serverPort} 포트에서 실행 중입니다.`);
    });
    });
    이렇게 저는 웹에 지도를 띄어서 출발지와 도착지를 두 마커로 지정했을 때 vscode의 터미널 창에 server.js를 실행하여 mongodb의 mapdata에 calculate 라는 collection을 만들고,
    server.js 실행에서 빠져나온 후 터미널 창에 ~~\public>geo.py 를 실행하여 계산된 예측시간을 화면에 띄우는게 목표입니다.
    하지만 둘 다 실행은 잘 되지만 mongodb에 들어가면 mapdata 에 calculate 가 저장되지 않고 터미널에서
    127.0.0.1 - - [04/Jun/2023 06:21:36] code 400, message Bad request version ('3.10.7.final.0\x00\x00\x00')
    127.0.0.1 - - [04/Jun/2023 06:21:36] "\x0c\x01\x00\x00Cd\x00\x00\x00\x00\x00\x00Ô\x07\x00\x00\x00\x00\x00\x00admin.$cmd\x00\x00\x00\x00\x00ÿÿÿÿå\x00\x00\x00\x10ismaster\x00\x01\x00\x00\x00\x08helloOk\x00\x01\x03client\x00À\x00\x00\x00\x03driver\x00*\x00\x00\x00\x02name\x00\x08\x00\x00\x00PyMongo\x00\x02version\x00\x06\x00\x00\x004.3.3\x00\x00\x03os\x00`\x00\x00\x00\x02type\x00\x08\x00\x00\x00Windows\x00\x02name\x00\x0b\x00\x00\x00Windows 10\x00\x02architecture\x00\x06\x00\x00\x00AMD64\x00\x02version\x00\x0f\x00\x00\x0010.0.22621-SP0\x00\x00\x02platform\x00\x17\x00\x00\x00CPython 3.10.7.final.0\x00\x00\x00" HTTPStatus.BAD_REQUEST -
    이런 에러가 뜹니다... 발표용으로 제작 중인데 원인을 찾아봐도 모르겠어요... 혹시 수정해야 할 부분이 있을까요? 
    
    
    
     
    
    
     
     
     
     
    #85759

    codingapple
    키 마스터
    res.json(predictedTime); 같은건 db저장하는 콜백함수안에 넣어봅시다
2 글 보임 - 1 에서 2 까지 (총 2 중에서)
  • 답변은 로그인 후 가능합니다.

About

현재 월 700명 신규수강중입니다.

  (09:00~20:00) 빠른 상담은 카톡 플러스친구 코딩애플 (링크)
  admin@codingapple.com
  이용약관
ⓒ Codingapple, 강의 예제, 영상 복제 금지
top

© Codingapple, All rights reserved. 슈퍼로켓 에듀케이션 / 서울특별시 강동구 고덕로 19길 30 / 사업자등록번호 : 212-26-14752 온라인 교육학원업 / 통신판매업신고번호 : 제 2017-서울강동-0002 호 / 개인정보관리자 : 박종흠