database separate file
This commit is contained in:
@@ -1,53 +1,19 @@
|
|||||||
from flask import Flask, request, jsonify, render_template, redirect, url_for, flash
|
from flask import Flask, request, jsonify, render_template, redirect, url_for, flash
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import requests
|
from .mir_server import execute_mission # Import the execute_mission function
|
||||||
import base64
|
from .models import db, Log, MirServerSettings, BoardSettings, MissionStatus # Import the models
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///logs.db'
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///logs.db'
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
app.secret_key = 'supersecretkey'
|
app.secret_key = 'supersecretkey'
|
||||||
db = SQLAlchemy(app)
|
db.init_app(app) # Initialize the database with the app
|
||||||
|
|
||||||
class Log(db.Model):
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
hostname = db.Column(db.String(100), nullable=False)
|
|
||||||
ip_address = db.Column(db.String(100), nullable=False)
|
|
||||||
message = db.Column(db.String(500), nullable=False)
|
|
||||||
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
|
|
||||||
relay1_status = db.Column(db.String(3), default='off')
|
|
||||||
relay2_status = db.Column(db.String(3), default='off')
|
|
||||||
relay3_status = db.Column(db.String(3), default='off')
|
|
||||||
relay4_status = db.Column(db.String(3), default='off')
|
|
||||||
input1_status = db.Column(db.String(3), default='off')
|
|
||||||
input2_status = db.Column(db.String(3), default='off')
|
|
||||||
input3_status = db.Column(db.String(3), default='off')
|
|
||||||
input4_status = db.Column(db.String(3), default='off')
|
|
||||||
mission1 = db.Column(db.String(100), default='')
|
|
||||||
mission2 = db.Column(db.String(100), default='')
|
|
||||||
mission3 = db.Column(db.String(100), default='')
|
|
||||||
mission4 = db.Column(db.String(100), default='')
|
|
||||||
|
|
||||||
class MirServerSettings(db.Model):
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
ip_address = db.Column(db.String(100), nullable=False)
|
|
||||||
user = db.Column(db.String(100), nullable=False)
|
|
||||||
password = db.Column(db.String(100), nullable=False)
|
|
||||||
auth_header = db.Column(db.String(500), nullable=False)
|
|
||||||
|
|
||||||
class BoardSettings(db.Model):
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
hostname = db.Column(db.String(100), nullable=False)
|
|
||||||
mission1 = db.Column(db.String(100), nullable=False)
|
|
||||||
mission2 = db.Column(db.String(100), nullable=False)
|
|
||||||
mission3 = db.Column(db.String(100), nullable=False)
|
|
||||||
mission4 = db.Column(db.String(100), nullable=False)
|
|
||||||
|
|
||||||
# Create the database if it does not exist
|
# Create the database if it does not exist
|
||||||
if not os.path.exists('instance/logs.db'):
|
if not os.path.exists('instance/logs.db'):
|
||||||
|
os.makedirs('instance', exist_ok=True)
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
|
||||||
@@ -101,6 +67,8 @@ def log_message():
|
|||||||
action = 'on' if "pressed" in message else 'off'
|
action = 'on' if "pressed" in message else 'off'
|
||||||
if input_index == 1:
|
if input_index == 1:
|
||||||
input1_status = action
|
input1_status = action
|
||||||
|
if action == 'on':
|
||||||
|
initiate_mission(hostname, 1)
|
||||||
elif input_index == 2:
|
elif input_index == 2:
|
||||||
input2_status = action
|
input2_status = action
|
||||||
elif input_index == 3:
|
elif input_index == 3:
|
||||||
@@ -235,10 +203,11 @@ def control_relay(hostname, relay, action):
|
|||||||
@app.route('/settings', methods=['GET'])
|
@app.route('/settings', methods=['GET'])
|
||||||
def settings():
|
def settings():
|
||||||
cleanup_time = app.config.get('CLEANUP_TIME', 24)
|
cleanup_time = app.config.get('CLEANUP_TIME', 24)
|
||||||
mir_ip = app.config.get('MIR_IP', '')
|
mir_settings = MirServerSettings.query.first()
|
||||||
mir_user = app.config.get('MIR_USER', '')
|
mir_ip = mir_settings.ip_address if mir_settings else ''
|
||||||
mir_password = app.config.get('MIR_PASSWORD', '')
|
mir_user = mir_settings.user if mir_settings else ''
|
||||||
mir_auth_header = app.config.get('MIR_AUTH_HEADER', '')
|
mir_password = mir_settings.password if mir_settings else ''
|
||||||
|
mir_auth_header = mir_settings.auth_header if mir_settings else ''
|
||||||
boards = BoardSettings.query.all()
|
boards = BoardSettings.query.all()
|
||||||
board_settings = []
|
board_settings = []
|
||||||
for board in boards:
|
for board in boards:
|
||||||
@@ -268,10 +237,21 @@ def set_mir_server():
|
|||||||
mir_password = request.form.get('mir_password')
|
mir_password = request.form.get('mir_password')
|
||||||
mir_auth_header = request.form.get('mir_auth_header')
|
mir_auth_header = request.form.get('mir_auth_header')
|
||||||
if mir_ip and mir_user and mir_password and mir_auth_header:
|
if mir_ip and mir_user and mir_password and mir_auth_header:
|
||||||
app.config['MIR_IP'] = mir_ip
|
mir_settings = MirServerSettings.query.first()
|
||||||
app.config['MIR_USER'] = mir_user
|
if mir_settings:
|
||||||
app.config['MIR_PASSWORD'] = mir_password
|
mir_settings.ip_address = mir_ip
|
||||||
app.config['MIR_AUTH_HEADER'] = mir_auth_header
|
mir_settings.user = mir_user
|
||||||
|
mir_settings.password = mir_password
|
||||||
|
mir_settings.auth_header = mir_auth_header
|
||||||
|
else:
|
||||||
|
mir_settings = MirServerSettings(
|
||||||
|
ip_address=mir_ip,
|
||||||
|
user=mir_user,
|
||||||
|
password=mir_password,
|
||||||
|
auth_header=mir_auth_header
|
||||||
|
)
|
||||||
|
db.session.add(mir_settings)
|
||||||
|
db.session.commit()
|
||||||
flash('MIR Server settings updated successfully!', 'success')
|
flash('MIR Server settings updated successfully!', 'success')
|
||||||
else:
|
else:
|
||||||
flash('Invalid MIR Server settings!', 'danger')
|
flash('Invalid MIR Server settings!', 'danger')
|
||||||
@@ -327,6 +307,21 @@ def get_input_status(hostname):
|
|||||||
return jsonify({'input_status': input_status})
|
return jsonify({'input_status': input_status})
|
||||||
return jsonify({'input_status': ['off', 'off', 'off', 'off']})
|
return jsonify({'input_status': ['off', 'off', 'off', 'off']})
|
||||||
|
|
||||||
|
@app.route('/board/<hostname>/mission_status', methods=['GET'])
|
||||||
|
def get_mission_status(hostname):
|
||||||
|
mission_status = MissionStatus.query.filter_by(hostname=hostname).order_by(MissionStatus.id.desc()).first()
|
||||||
|
if mission_status:
|
||||||
|
return jsonify({
|
||||||
|
'step1': 'Started' if mission_status.status == 'Started' else 'Pending',
|
||||||
|
'step2': 'Pending',
|
||||||
|
'mission': mission_status.status
|
||||||
|
})
|
||||||
|
return jsonify({
|
||||||
|
'step1': 'Pending',
|
||||||
|
'step2': 'Pending',
|
||||||
|
'mission': 'Pending'
|
||||||
|
})
|
||||||
|
|
||||||
def post_action_to_server(hostname, action):
|
def post_action_to_server(hostname, action):
|
||||||
url = "http://your-server-url.com/action"
|
url = "http://your-server-url.com/action"
|
||||||
payload = {
|
payload = {
|
||||||
@@ -342,23 +337,47 @@ def post_action_to_server(hostname, action):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error posting action: {e}")
|
print(f"Error posting action: {e}")
|
||||||
|
|
||||||
def execute_mission(mission_id):
|
def initiate_mission(hostname, input_index):
|
||||||
mir_ip = app.config.get('MIR_IP')
|
board_settings = BoardSettings.query.filter_by(hostname=hostname).first()
|
||||||
mir_user = app.config.get('MIR_USER')
|
if not board_settings:
|
||||||
mir_password = app.config.get('MIR_PASSWORD')
|
return
|
||||||
url = f"http://{mir_ip}/api/v2.0.0/missions/{mission_id}/dispatch"
|
|
||||||
|
mission_id = getattr(board_settings, f'mission{input_index}')
|
||||||
|
if not mission_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
execute_mission(mission_id, hostname)
|
||||||
|
mission_status = MissionStatus(hostname=hostname, mission_id=mission_id, status='Started')
|
||||||
|
db.session.add(mission_status)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
def fetch_mission_status():
|
||||||
|
with app.app_context():
|
||||||
|
missions = MissionStatus.query.filter_by(status='Started').all()
|
||||||
|
mir_settings = MirServerSettings.query.first()
|
||||||
|
if not mir_settings:
|
||||||
|
print("MIR server settings not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
mir_ip = mir_settings.ip_address
|
||||||
|
auth_header = mir_settings.auth_header
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': f'Basic {base64.b64encode(f"{mir_user}:{mir_password}".encode()).decode()}'
|
'Authorization': auth_header
|
||||||
}
|
}
|
||||||
|
for mission in missions:
|
||||||
|
url = f"http://{mir_ip}/api/v2.0.0/missions/{mission.mission_guid}" # Use mission_guid
|
||||||
try:
|
try:
|
||||||
response = requests.post(url, headers=headers)
|
response = requests.get(url, headers=headers)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print(f"Mission {mission_id} executed successfully.")
|
mission_data = response.json()
|
||||||
|
mission.status = mission_data.get('state', 'Pending')
|
||||||
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
print(f"Failed to execute mission {mission_id}: {response.text}")
|
print(f"Failed to fetch mission status {mission.mission_id}: {response.text}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error executing mission {mission_id}: {e}")
|
print(f"Error fetching mission status {mission.mission_id}: {e}")
|
||||||
|
threading.Timer(30, fetch_mission_status).start()
|
||||||
|
|
||||||
def schedule_cleanup():
|
def schedule_cleanup():
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
@@ -369,4 +388,5 @@ def schedule_cleanup():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
schedule_cleanup() # Start the cleanup scheduler
|
schedule_cleanup() # Start the cleanup scheduler
|
||||||
app.run(host='0.0.0.0', port=5000)
|
fetch_mission_status() # Start fetching mission status
|
||||||
|
app.run(host='0.0.0.0', port=80)
|
||||||
Binary file not shown.
33
server_api/mir_server.py
Normal file
33
server_api/mir_server.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import requests
|
||||||
|
from .models import MirServerSettings, MissionStatus
|
||||||
|
from . import db
|
||||||
|
|
||||||
|
def execute_mission(mission_id, hostname):
|
||||||
|
mir_settings = MirServerSettings.query.first()
|
||||||
|
if not mir_settings:
|
||||||
|
print("MIR server settings not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
mir_ip = mir_settings.ip_address
|
||||||
|
auth_header = mir_settings.auth_header
|
||||||
|
url = f"http://{mir_ip}/api/v2.0.0/mission_scheduler"
|
||||||
|
headers = {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'Authorization': auth_header,
|
||||||
|
'Accept-Language': 'en_US',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(url, headers=headers, json={"mission_id": mission_id})
|
||||||
|
if response.status_code in {200, 201}:
|
||||||
|
print(f"Mission {mission_id} executed successfully.")
|
||||||
|
mission_data = response.json()
|
||||||
|
mission_guid = mission_data.get('id')
|
||||||
|
mission_status = MissionStatus(hostname=hostname, mission_id=mission_id, mission_guid=mission_guid, status='Started')
|
||||||
|
db.session.add(mission_status)
|
||||||
|
db.session.commit()
|
||||||
|
else:
|
||||||
|
print(f"Failed to execute mission {mission_id}: {response.text}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error executing mission {mission_id}: {e}")
|
||||||
45
server_api/models.py
Normal file
45
server_api/models.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
class Log(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
hostname = db.Column(db.String(100), nullable=False)
|
||||||
|
ip_address = db.Column(db.String(100), nullable=False)
|
||||||
|
message = db.Column(db.String(500), nullable=False)
|
||||||
|
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
relay1_status = db.Column(db.String(3), default='off')
|
||||||
|
relay2_status = db.Column(db.String(3), default='off')
|
||||||
|
relay3_status = db.Column(db.String(3), default='off')
|
||||||
|
relay4_status = db.Column(db.String(3), default='off')
|
||||||
|
input1_status = db.Column(db.String(3), default='off')
|
||||||
|
input2_status = db.Column(db.String(3), default='off')
|
||||||
|
input3_status = db.Column(db.String(3), default='off')
|
||||||
|
input4_status = db.Column(db.String(3), default='off')
|
||||||
|
mission1 = db.Column(db.String(100), default='')
|
||||||
|
mission2 = db.Column(db.String(100), default='')
|
||||||
|
mission3 = db.Column(db.String(100), default='')
|
||||||
|
mission4 = db.Column(db.String(100), default='')
|
||||||
|
|
||||||
|
class MirServerSettings(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
ip_address = db.Column(db.String(100), nullable=False)
|
||||||
|
user = db.Column(db.String(100), nullable=False)
|
||||||
|
password = db.Column(db.String(100), nullable=False)
|
||||||
|
auth_header = db.Column(db.String(500), nullable=False)
|
||||||
|
|
||||||
|
class BoardSettings(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
hostname = db.Column(db.String(100), nullable=False)
|
||||||
|
mission1 = db.Column(db.String(100), nullable=False)
|
||||||
|
mission2 = db.Column(db.String(100), nullable=False)
|
||||||
|
mission3 = db.Column(db.String(100), nullable=False)
|
||||||
|
mission4 = db.Column(db.String(100), nullable=False)
|
||||||
|
|
||||||
|
class MissionStatus(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
hostname = db.Column(db.String(100), nullable=False)
|
||||||
|
mission_id = db.Column(db.String(100), nullable=False)
|
||||||
|
mission_guid = db.Column(db.String(100), nullable=True) # Add this field
|
||||||
|
status = db.Column(db.String(100), nullable=False, default='Pending')
|
||||||
@@ -149,6 +149,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h3>MIR Mission Status</h3>
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Mission Execution Steps</h5>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Step 1: Receiving start trigger from the board input
|
||||||
|
<span id="step-1-status" class="badge badge-secondary">Pending</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Step 2: Posting mission to MIR server
|
||||||
|
<span id="step-2-status" class="badge badge-secondary">Pending</span>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
Step 3: Mission execution status
|
||||||
|
<span id="mission-status" class="badge badge-secondary">Pending</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
@@ -182,6 +204,20 @@
|
|||||||
.catch(error => console.error('Error fetching input status:', error));
|
.catch(error => console.error('Error fetching input status:', error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchMissionStatus() {
|
||||||
|
fetch(`/board/{{ hostname }}/mission_status`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
document.getElementById('step-1-status').className = `badge badge-${data.step1}`;
|
||||||
|
document.getElementById('step-1-status').innerText = data.step1;
|
||||||
|
document.getElementById('step-2-status').className = `badge badge-${data.step2}`;
|
||||||
|
document.getElementById('step-2-status').innerText = data.step2;
|
||||||
|
document.getElementById('mission-status').className = `badge badge-${data.mission}`;
|
||||||
|
document.getElementById('mission-status').innerText = data.mission;
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching mission status:', error));
|
||||||
|
}
|
||||||
|
|
||||||
function startTimer() {
|
function startTimer() {
|
||||||
let timer = 5;
|
let timer = 5;
|
||||||
const timerElement = document.getElementById('timer');
|
const timerElement = document.getElementById('timer');
|
||||||
@@ -199,6 +235,7 @@
|
|||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
startTimer();
|
startTimer();
|
||||||
|
setInterval(fetchMissionStatus, 30000); // Fetch mission status every 30 seconds
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user