diff --git a/am_i_up/client.py b/am_i_up/client.py new file mode 100644 index 0000000..f681958 --- /dev/null +++ b/am_i_up/client.py @@ -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()) + + diff --git a/am_i_up/am_i_up.py b/am_i_up/server.py similarity index 79% rename from am_i_up/am_i_up.py rename to am_i_up/server.py index 0de3ffc..e1038ee 100644 --- a/am_i_up/am_i_up.py +++ b/am_i_up/server.py @@ -12,6 +12,8 @@ from aiohttp import web import time from ament_index_python import get_package_share_directory import yaml +import ipaddress +import subprocess def main(): facts = Facts() @@ -34,6 +36,18 @@ class Facts: def get_uptime(self): 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): env = {} # We're not going to return the whole environment because @@ -77,8 +91,10 @@ class Routes: return web.Response(text=text) async def ping(self, request): - text = 'pong' - return web.Response(text=text) + request_dict = await request.json() + result = self._facts.do_ping(request_dict['address']) + resp = {"message": result} + return web.json_response(resp) async def uptime(self, request): resp = {"uptime": self._facts.get_uptime()} @@ -95,3 +111,11 @@ class Routes: async def env(self, request): env = self._facts.get_env() return web.json_response(env) + + +def is_valid_ip(address): + try: + ipaddress.ip_address(address) + return True + except ValueError: + return False diff --git a/setup.py b/setup.py index c6b4419..2c6498e 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,8 @@ setup( license='MPL 2.0', entry_points={ 'console_scripts': [ - 'am_i_up = am_i_up.am_i_up:main', + 'server = am_i_up.server:main', + 'client = am_i_up.client:main' ], }, )