Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard Connection #250

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion field_friend/system.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import logging
import os
from typing import Any
from typing import Any, cast

import icecream
import numpy as np
import psutil
import requests
import rosys
from rosys.version import __version__ as rosys_version

import config.config_selection as config_selector

Expand Down Expand Up @@ -44,11 +46,15 @@
class System(rosys.persistence.PersistentModule):

version = 'unknown' # This is set in main.py through the environment variable VERSION or ROBOT_ID
robot_id = 'unknown' # This is set in main.py through the environment variable ROBOT_ID

def __init__(self) -> None:
super().__init__()
assert self.version is not None
assert self.version != 'unknown'
assert self.robot_id is not None
assert self.robot_id != 'unknown'

rosys.hardware.SerialCommunication.search_paths.insert(0, '/dev/ttyTHS0')
self.log = logging.getLogger('field_friend.system')
self.is_real = rosys.hardware.SerialCommunication.is_possible()
Expand Down Expand Up @@ -110,6 +116,10 @@ def watch_robot() -> None:
self.plant_locator = PlantLocator(self)

rosys.on_repeat(watch_robot, 1.0)
if self.is_real and os.environ.get('DASHBOARD_URL'):
rosys.on_repeat(self.send_status_to_robot_dashboard, 60)
else:
rosys.notify('Dashboard URL is not set', type='negative')

self.path_provider = PathProvider()
self.field_provider = FieldProvider()
Expand Down Expand Up @@ -263,3 +273,49 @@ def log_status(self):

bms_logger = logging.getLogger('field_friend.bms')
bms_logger.info(f'Battery: {self.field_friend.bms.state.short_string}')

async def send_status_to_robot_dashboard(self) -> None:
dashboard_url = os.environ.get('DASHBOARD_URL')
try:
status = 'emergency stop' if len(self.field_friend.estop.pressed_estops) > 0 or self.field_friend.estop.is_soft_estop_active else \
'bumper active' if self.field_friend.bumper and self.field_friend.bumper.active_bumpers else \
'working' if self.automator.automation is not None and self.automator.automation.is_running else \
'idle'
if self.is_real:
lizard_firmware = cast(FieldFriendHardware, self.field_friend).robot_brain.lizard_firmware
await lizard_firmware.read_core_version()
await lizard_firmware.read_p0_version()
core_version = lizard_firmware.core_version
p0_version = lizard_firmware.p0_version
else:
core_version = 'simulation'
p0_version = 'simulation'
if self.current_navigation is not None and self.current_navigation is FieldNavigation:
field = self.field_navigation.field if self.field_navigation.field is not None else None
row = self.field_navigation.current_row if self.field_navigation.current_row is not None else None
else:
field = None
row = None
position = self.gnss.current.location if self.gnss.current is not None else None
data = {
'version': self.version,
'battery': self.field_friend.bms.state.percentage,
'battery_charging': self.field_friend.bms.state.is_charging,
'status': status,
'position': {'lat': position.lat, 'long': position.long} if position is not None else None,
# TODO: update the gnss quality with kalman filter
'gnss_quality': self.gnss.current.gps_qual if self.gnss.current is not None else None,
'implement': self.field_friend.implement_name,
'navigation': self.current_navigation.name if self.current_navigation is not None else None,
'field': field,
'row': row,
'rosys_version': rosys_version,
'core_lizard_version': core_version,
'p0_lizard_version': p0_version,
}
endpoint = f'{dashboard_url}/api/robot/{self.robot_id.lower()}'
response = requests.post(endpoint, json=data, timeout=5)
if response.status_code != 200:
rosys.notify(f'Failed to send status. Response code {response.status_code}', type='negative')
except Exception as e:
rosys.notify(f'Error sending status: {e!s}', type='negative')
1 change: 1 addition & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def startup() -> None:
return
logger.info('Starting Field Friend for robot %s', robot_id)
System.version = os.environ.get('VERSION') or robot_id
System.robot_id = robot_id
system = System()

interface.main_page(system) # /
Expand Down
Loading