Add client. Fill in server.

This commit is contained in:
James Pace 2025-12-21 14:54:45 +00:00
parent c8385f4b55
commit 48eb1a1cbe
3 changed files with 70 additions and 3 deletions

42
am_i_up/client.py Normal file
View File

@ -0,0 +1,42 @@
#
# Copyright 2025 James Pace
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
#
import aiohttp
import asyncio
import rclpy
import json
def main(args=None):
rclpy.init(args=args)
node = rclpy.create_node('am_i_up_client')
action = node.declare_parameter('action', value="").value
options = node.declare_parameter('options', value=[""]).value
if "" == action:
raise RunTimeError("Need to provide an action to take.")
if action == 'ping':
asyncio.run(call_ping(options))
async def call_ping(options):
if len(options) != 1 or options[0] == "":
raise RunTimeError("Ping option is an address as a string.")
request = {"address": options[0]}
print("Calling ping with request: {}", json.dumps(request))
async with aiohttp.ClientSession() as session:
async with session.get('http://localhost:8080/ping', json=request) as resp:
print(await resp.text())

View File

@ -12,6 +12,8 @@ from aiohttp import web
import time import time
from ament_index_python import get_package_share_directory from ament_index_python import get_package_share_directory
import yaml import yaml
import ipaddress
import subprocess
def main(): def main():
facts = Facts() facts = Facts()
@ -34,6 +36,18 @@ class Facts:
def get_uptime(self): def get_uptime(self):
return time.monotonic() - self._start_time return time.monotonic() - self._start_time
def do_ping(self, address):
# Make sure address is a ip address.
if not is_valid_ip(address):
return "Provied address ({}) is not valid.".format(address)
# Build command.
command = ["ping", "-W", "1", "-c", "1", address]
process = subprocess.run(command)
if process.returncode == 0:
return "{} responded to ping.".format(address)
return "{} did not respond to ping.".format(address)
def get_env(self): def get_env(self):
env = {} env = {}
# We're not going to return the whole environment because # We're not going to return the whole environment because
@ -77,8 +91,10 @@ class Routes:
return web.Response(text=text) return web.Response(text=text)
async def ping(self, request): async def ping(self, request):
text = 'pong' request_dict = await request.json()
return web.Response(text=text) result = self._facts.do_ping(request_dict['address'])
resp = {"message": result}
return web.json_response(resp)
async def uptime(self, request): async def uptime(self, request):
resp = {"uptime": self._facts.get_uptime()} resp = {"uptime": self._facts.get_uptime()}
@ -95,3 +111,11 @@ class Routes:
async def env(self, request): async def env(self, request):
env = self._facts.get_env() env = self._facts.get_env()
return web.json_response(env) return web.json_response(env)
def is_valid_ip(address):
try:
ipaddress.ip_address(address)
return True
except ValueError:
return False

View File

@ -18,7 +18,8 @@ setup(
license='MPL 2.0', license='MPL 2.0',
entry_points={ entry_points={
'console_scripts': [ 'console_scripts': [
'am_i_up = am_i_up.am_i_up:main', 'server = am_i_up.server:main',
'client = am_i_up.client:main'
], ],
}, },
) )