integrate ros. remove front end.

This commit is contained in:
James Pace 2026-02-28 10:54:57 -05:00
parent f0574de8f4
commit d1d0a61569
6 changed files with 53 additions and 97 deletions

View File

@ -6,11 +6,6 @@ find_package(ament_cmake_python REQUIRED)
ament_python_install_package(${PROJECT_NAME})
install(DIRECTORY
front_end
DESTINATION share/${PROJECT_NAME}/
)
install(DIRECTORY
scripts/
DESTINATION lib/${PROJECT_NAME}/lib

View File

@ -8,66 +8,56 @@
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#
import asyncio
from aiohttp import web
import time
from ament_index_python import get_package_share_directory
import time
import yaml
import ipaddress
import subprocess
import os
from jinja2 import Environment, FileSystemLoader, select_autoescape
import rclpy
from std_msgs.msg import String
def main():
facts = Facts()
view = View(facts)
api = Api(facts)
ros = Ros(facts)
app = web.Application()
app.add_routes([
web.get('/', view.root),
web.get('/ping', view.ping),
web.get('/api/ping', api.ping),
web.get('/api/uptime', api.uptime),
web.get('/api/build_info', api.build_info),
web.get('/api/env', api.env),
web.static('/static', view.get_static_dir())
])
web.run_app(app)
future = asyncio.gather(api.run(), ros.run())
asyncio.get_event_loop().run_until_complete(future)
class View:
class Ros:
def __init__(self, facts):
rclpy.init()
self._facts = facts
self._env = Environment(
loader=FileSystemLoader(self._find_template_dirs()),
autoescape=select_autoescape()
)
self._node = rclpy.create_node('am_i_up')
async def root(self, request):
text = self._env.get_template('home.html').render()
return web.Response(text=text, content_type='text/html')
self._node.create_subscription(String, "status", self.status_sub, 1)
async def ping(self, request):
text = self._env.get_template('ping.html').render()
return web.Response(text=text, content_type='text/html')
def status_sub(self, msg):
self._facts.set_status_string(msg.data)
def _find_template_dirs(self):
package_dir = get_package_share_directory('am_i_up')
template_dir = "{}/front_end/templates".format(package_dir)
if not os.path.exists(template_dir):
raise RuntimeError("Could not find template_dir: {}".format(template_dir))
return [template_dir]
async def run(self):
while rclpy.ok():
rclpy.spin_once(self._node, timeout_sec=0)
await asyncio.sleep(1e-4)
def get_static_dir(self):
package_dir = get_package_share_directory('am_i_up')
static_dir = "{}/front_end/static".format(package_dir)
if not os.path.exists(static_dir):
raise RuntimeError("Could not find static_dir: {}".format(static_dir))
return static_dir
class Facts:
def __init__(self):
self._start_time = time.monotonic()
self._status_string = None
def set_status_string(self, status):
self._status_string = status
def get_status(self):
return self._status_string
def get_uptime(self):
return time.monotonic() - self._start_time
@ -122,6 +112,25 @@ class Api:
def __init__(self, facts):
self._facts = facts
async def run(self):
app = web.Application()
app.add_routes([
web.get('/api/ping', self.ping),
web.get('/api/uptime', self.uptime),
web.get('/api/build_info', self.build_info),
web.get('/api/env', self.env),
web.get('/api/status', self.status)
])
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, 'localhost', 8080)
await site.start()
while rclpy.ok():
await asyncio.sleep(3600)
await runner.cleanup()
async def ping(self, request):
request_dict = await request.json()
result = self._facts.do_ping(request_dict['address'])
@ -144,6 +153,13 @@ class Api:
env = self._facts.get_env()
return web.json_response(env)
async def status(self, request):
status = self._facts.get_status()
if not status:
status = "Nothing received!"
resp = {"message": status}
return web.json_response(resp)
def is_valid_ip(address):
try:
ipaddress.ip_address(address)

View File

@ -1,6 +0,0 @@
.padded {
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
padding-bottom: 10px;
}

View File

@ -1,39 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link href="/static/css/base.css" rel="stylesheet">
<title>{% block title %}Robot Status UI{% endblock %}</title>
</head>
<body>
<!-- NavBar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light padded">
<a class="navbar-brand" href="/">am i up?</a>
<div class="navbar-nav">
<a class="nav-item nav-link" href="/">Home</a>
<a class="nav-item nav-link" href="/ping">Ping</a>
<a class="nav-item nav-link" href="/version">Software Version</a>
</div>
</nav>
<!-- Content -->
<div class="container">
{% block content %}
{% endblock %}
</div>
<!-- Load JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"></script>
{% block js %}{% endblock %}
</body>
</html>

View File

@ -1,5 +0,0 @@
{% extends "base.html" %}
{% block content %}
<p>Home</p>
{% endblock %}

View File

@ -1,5 +0,0 @@
{% extends "base.html" %}
{% block content %}
<p>Ping</p>
{% endblock %}