Created
June 28, 2021 23:09
-
-
Save drewrothstein/4e7c4f8aee19d8297a35561fbe4806ef to your computer and use it in GitHub Desktop.
Automower Action Data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import datetime | |
import time | |
from shapely import geometry | |
import geopandas as gpd | |
import pandas as pd | |
import requests | |
import timeago | |
MOWER_NAME = 'Fred' | |
# Source: github.com/chrisz/pyhusmow | |
# ./husmow --login <> --password <> server | |
DATA_API = 'http://127.0.0.1:1234/status' | |
TIME_BETWEEN_CHECKS_SECONDS = 30 | |
# API to Save Location | |
SAVE_API = 'https://us-central1-<XXXXXXX TODO XXXXXXX>.cloudfunctions.net/automower' | |
# Counter-clockwise Boundary Boxes: [(Bottom-left), (Bottom-right), (Top-right), (Top-left)] | |
CRS = {'init': 'epsg:4326'} # https://epsg.io/4326 | |
# XXXXXXX TODO XXXXXXX | |
AREA_HILL = [(41.049734, -33.577369),(41.049750, -33.897128),(41.050419, -33.897219),(41.050417, -33.867487)] | |
AREA_PATH = [(41.049734, -33.857120), (41.049824, -33.875063), (41.049949, -33.896138), (41.049873, -33.897168)] | |
AREA_FRONT = [(41.049895, -33.896023), (41.049861, -33.895808), (41.050236, -33.894636), (41.050300, -33.896102)] | |
AREA_SIDE = [(45.050226, -33.895870), (45.050238, -33.895608), (45.046371, -33.895570), (45.050379, -33.856948)] | |
AREA_BACK = [(45.049804, -33.874686), (45.049839, -33.895298), (45.050329, -33.895336), (45.050242, -33.895623)] | |
def save_automower_location(message): | |
params = {'message': message} | |
r = requests.post(SAVE_API, params=params) | |
r.raise_for_status() | |
def get_mower_status(): | |
r = requests.get(DATA_API) | |
# 1624880445224 | |
timestamp = r.json()['storedTimestamp'] | |
# [{'latitude': 87.0499532, 'longitude': -89.8958507, 'gpsStatus': 'USING_GPS_MAP'}] | |
location = r.json()['lastLocations'] | |
# {'latitude': 87.0499532, 'longitude': -89.8958507, 'gpsStatus': 'USING_GPS_MAP'} | |
loc0 = location[0] | |
# 100 | |
battery = r.json()['batteryPercent'] | |
# OK_LEAVING | |
status = r.json()['mowerStatus'] | |
return timestamp, loc0, battery, status | |
def convert_timestamp_to_human(timestamp): | |
now = datetime.datetime.now() | |
timestamp_seconds = timestamp / 1000.0 | |
date = datetime.datetime.fromtimestamp(timestamp_seconds) | |
return (timeago.format(date, now)) | |
def check_automower_in_box(location, point_list): | |
in_box = False | |
poly = geometry.Polygon(point_list) | |
spoly = gpd.GeoSeries([poly],crs=CRS) | |
geo_data = [geometry.Point(location['latitude'], location['longitude'])] | |
dfpoints = gpd.GeoDataFrame(crs=CRS, geometry=geo_data) | |
subset = dfpoints[dfpoints.within(spoly.geometry.iloc[0])] | |
if subset.shape[0] > 0: | |
in_box = True | |
return in_box | |
def main(): | |
# 1624880445224, {'latitude': 89.0499532, 'longitude': -100.8958507, 'gpsStatus': 'USING_GPS_MAP'}, 100, 'OK_LEAVING' | |
timestamp, location, battery, status = get_mower_status() | |
# Examples: 25 seconds ago, just now | |
timestamp_human_formatted = convert_timestamp_to_human(timestamp) | |
# Check each boundary | |
message = '' | |
if 'PARK' in status or 'CHARG' in status: | |
message = '{0} is charging with {1} percent battery'.format(MOWER_NAME, battery) | |
elif check_automower_in_box(location, AREA_HILL): | |
message = '{0} is on the front hill as of {1} with {2} percent battery'.format(MOWER_NAME, timestamp_human_formatted, battery) | |
elif check_automower_in_box(location, AREA_PATH): | |
message = '{0} is on the front path to the hill as of {1} with {2} percent battery'.format(MOWER_NAME, timestamp_human_formatted, battery) | |
elif check_automower_in_box(location, AREA_FRONT): | |
message = '{0} is in the front of the house as of {1} with {2} percent battery'.format(MOWER_NAME, timestamp_human_formatted, battery) | |
elif check_automower_in_box(location, AREA_SIDE): | |
message = '{0} is on the side of the house as of {1} with {2} percent battery'.format(MOWER_NAME, timestamp_human_formatted, battery) | |
elif check_automower_in_box(location, AREA_BACK): | |
message = '{0} is in the back of the house as of {1} with {2} percent battery'.format(MOWER_NAME, timestamp_human_formatted, battery) | |
else: | |
message = '{0} is not able to be located as of {1}'.format(MOWER_NAME, timestamp_human_formatted) | |
save_automower_location(message) | |
while True: | |
main() | |
time.sleep(TIME_BETWEEN_CHECKS_SECONDS) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment