Skip to content

Commit

Permalink
Version 2.6.3
Browse files Browse the repository at this point in the history
Signed-off-by: mctinker <[email protected]>
  • Loading branch information
mctinker authored Jan 15, 2024
1 parent 9f91bd4 commit 88253a1
Show file tree
Hide file tree
Showing 15 changed files with 634 additions and 303 deletions.
32 changes: 17 additions & 15 deletions maptasker/src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,29 @@
DARK_MODE = True

#
# Set up to fetch the backup file from Android device running the Tasker server
# Set up to fetch the backup file from Android device running the Tasker server.
#
# The following two parameters must both be filled in for the fetch to work:
# BACKUP_FILE_HTTP is the Tasker server ip address and port number on the Android
# device from which to fetch the file
# BACKUP_FILE_LOCATION is the location of the backup file on the Android device
#
# In addition, the Tasker HTTP sample Project must be active on the Android device
# (https://taskernet.com/shares/?user=AS35m8ne7oO4s%2BaDx%2FwlzjdFTfVMWstg1ay5AkpiNdrLoSXEZdFfw1IpXiyJCVLNW0yn&id=Project%3AHttp+Server+Example),
# and the server must be active.
# In addition, the Tasker HTTP sample Project must be installed on the Android device,
# found at...
# (https://shorturl.at/bwCD4),
# and the server must be active on the Android device.

# This is the HTTP IP address of the Android device from which to fetch the backup.
# Example: ANDROID_IPADDR = "192.168.0.210"

ANDROID_IPADDR = ""

# This is the HTTP IP address and port number (e.g. 1821) that Tasker assigns to the
# server on the device containing the backup file to get.
# Example: BACKUP_FILE_HTTP = "http://192.168.0.210:1821" (note: not "https")
# This is the port number for the Android device from which to fetch the backup,
# and is specified in the Tasker HTTP Server Example project notification.
# From notification: HTTP Server Info {"device_name":"http://192.168.0.49:1821"}
# Example: ANDROID_PORT = "1821"

BACKUP_FILE_HTTP = ""
ANDROID_PORT = ""

# This is the location on the Android device from which to pull the backup file
# Example: BACKUP_FILE_LOCATION = "/Tasker/configs/user/backup.xml"
# Example: ANDROID_FILE = "/Tasker/configs/user/backup.xml"

BACKUP_FILE_LOCATION = ""
ANDROID_FILE = ""

# ##################################################################################
# END User-modifiable global constants
Expand Down
10 changes: 4 additions & 6 deletions maptasker/src/frontmtr.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,13 @@ def output_the_heading() -> None:
if PrimeItems.program_arguments["fetched_backup_from_android"]:
source_file = (
"From Android device"
f' {PrimeItems.program_arguments["backup_file_http"]} at'
f' {PrimeItems.program_arguments["backup_file_location"]}'
f' TCP IP address:{PrimeItems.program_arguments["android_ipaddr"]}'
f' on port:{PrimeItems.program_arguments["android_port"]}'
f' with file location: {PrimeItems.program_arguments["android_file"]}'
)
elif PrimeItems.program_arguments["debug"] or not PrimeItems.program_arguments["file"]:
filename = isinstance(PrimeItems.file_to_get, str)
if not filename:
filename = PrimeItems.file_to_get.name
else:
filename = PrimeItems.file_to_get
filename = PrimeItems.file_to_get.name if not filename else PrimeItems.file_to_get
source_file = filename
else:
source_file = PrimeItems.program_arguments["file"]
Expand Down
25 changes: 12 additions & 13 deletions maptasker/src/getbakup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ def write_out_backup_file(file_contents: bin) -> None:

# We are going to save the file as...
# Get position of the last "/" in path/file
name_location = PrimeItems.program_arguments["backup_file_location"].rfind("/") + 1
name_location = PrimeItems.program_arguments["android_file"].rfind("/") + 1
# Get the name of the file
my_file_name = PrimeItems.program_arguments["backup_file_location"][name_location:]
my_file_name = PrimeItems.program_arguments["android_file"][name_location:]

# Convert the binary code to string
output_lines = file_contents.decode("utf-8")

# Set up the backup file full path
the_backup_file = PrimeItems.program_arguments["backup_file_location"]
the_backup_file = PrimeItems.program_arguments["android_file"]
put_message = f"Fetching backup file {my_file_name}: {the_backup_file}"
logger.debug(put_message)

Expand All @@ -69,13 +69,11 @@ def write_out_backup_file(file_contents: bin) -> None:
# Set flag to identify that backup file was fetched from Android device
PrimeItems.program_arguments["fetched_backup_from_android"] = True

return


# ##################################################################################
# Issue HTTP Request to get the backup xml file from the Android device.
# ##################################################################################
def request_file(backup_file_http: str, backup_file_location: str) -> tuple[int, object]:
def request_file(ip_addr: str, port_number: str, file_location: str) -> tuple[int, object]:
"""
Issue HTTP Request to get the backup xml file from the Android device.
Tasker's HTTP Server Example must be installed for this to work:
Expand All @@ -88,8 +86,8 @@ def request_file(backup_file_http: str, backup_file_location: str) -> tuple[int,
# Create the URL to request the backup xml file from the Android device running the
# Tasker server.
# Something like: 192.168.0.210:1821/file/path/to/backup.xml?download=1
http = "http://" if "http://" not in backup_file_http else ""
url = f"{http}{backup_file_http}/file{backup_file_location}?download=1"
http = "http://" if "http://" not in ip_addr else ""
url = f"{http}{ip_addr}:{port_number}/file{file_location}?download=1"

# Make the request.
try:
Expand All @@ -115,7 +113,7 @@ def request_file(backup_file_http: str, backup_file_location: str) -> tuple[int,
# Return the contents of the file.
return 0, response.content
elif response.status_code == 404:
return 6, f"File '{backup_file_location}' not found."
return 6, f"File '{file_location}' not found."
else:
return (
8,
Expand Down Expand Up @@ -152,17 +150,18 @@ def get_backup_file() -> str:
"""
# Get the contents of the file.
return_code, file_contents = request_file(
PrimeItems.program_arguments["backup_file_http"],
PrimeItems.program_arguments["backup_file_location"],
PrimeItems.program_arguments["android_ipaddr"],
PrimeItems.program_arguments["android_port"],
PrimeItems.program_arguments["android_file"],
)

if return_code != 0:
if PrimeItems.program_arguments["gui"]:
PrimeItems.error_code = return_code
return
return None
error_handler(str(file_contents), 8)

# Process the backup file
write_out_backup_file(file_contents)

return substring_after_last(PrimeItems.program_arguments["backup_file_location"], "/")
return substring_after_last(PrimeItems.program_arguments["android_file"], "/")
31 changes: 28 additions & 3 deletions maptasker/src/getputer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,29 @@
# preserved. Contributors provide an express grant of patent rights. #
# #
# #################################################################################### #
from __future__ import annotations

import contextlib
import json
from pathlib import Path

from maptasker.src.error import error_handler
from maptasker.src.sysconst import ARGUMENTS_FILE


def corrupted_file(program_arguments, colors_to_use):
def corrupted_file(program_arguments, colors_to_use) -> None:
"""
Checks for corrupted settings file and handles error
Args:
program_arguments: Command line arguments
colors_to_use: Color settings
Returns:
None: Returns None
Processing Logic:
1. Checks settings file for corruption
2. Generates error message if corrupted
3. Returns error message and settings as dictionaries for GUI display
4. Does not restore corrupted settings, asks user to re-save"""
error_handler(
(
f"'-restore' option... The settings file, {ARGUMENTS_FILE} is"
Expand All @@ -33,8 +48,8 @@ def corrupted_file(program_arguments, colors_to_use):
"msg": (
"The settings file is corrupt or not compatible with the new verison of \
MapTasker!"
"The old settings can not be restored. Re-save your settings."
)
"The old settings can not be restored. Re-save your settings.",
),
}
return program_arguments, colors_to_use

Expand Down Expand Up @@ -94,4 +109,14 @@ def save_restore_args(
except json.decoder.JSONDecodeError: # no saved file
corrupted_file(program_arguments, colors_to_use)

# Convert old android device settings to new settings.
with contextlib.suppress(KeyError):
if program_arguments["backup_file_http"]:
temp_args = program_arguments["backup_file_http"].split(":")
program_arguments["android_ipaddr"] = temp_args[1][2:]
program_arguments["android_port"] = temp_args[2]
program_arguments["android_file"] = program_arguments["backup_file_location"]
del program_arguments["backup_file_http"]
del program_arguments["backup_file_location"]

return program_arguments, colors_to_use
103 changes: 62 additions & 41 deletions maptasker/src/guiutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
# #################################################################################### #
from __future__ import annotations

import contextlib
import os
from tkinter import font

from maptasker.src.colrmode import set_color_mode
from maptasker.src.lineout import LineOut
from maptasker.src.maputils import validate_ip_address, validate_port
from maptasker.src.nameattr import get_tk
from maptasker.src.primitem import PrimeItems
from maptasker.src.proginit import get_data_and_output_intro
Expand Down Expand Up @@ -126,68 +128,87 @@ def get_monospace_fonts() -> dict:
# ##################################################################################
# Ping the Android evice to make sure it is reachable.
# ##################################################################################
def ping_android_device(self, backup_info: str) -> tuple[bool, str]: # noqa: ANN001
def ping_android_device(self, ip_address: str, port_number: str, file_location: str) -> bool: # noqa: ANN001
# The following should return a list: [ip_address:port_number, file_location]
"""
Pings an Android device
Args:
backup_info: str - Backup information in ip_address:port_number,file_location format
Returns:
tuple[bool, str] - A tuple containing a bool for success/failure and a error message string
- If failure, returns True and a blank strings, else False and ip addr and location
ip_address: str - TCP IP address of the Android device
port_number: str - TCP port number of the Android device
file_location: str - File location on the Android device
Return:
Error: True if error, false if all is good.
Processing Logic:
- Splits the backup_info string into ip_address, port_number, and file_location
- Validates the IP address, port number, and file location
- Pings the IP address to check connectivity
- Returns a tuple indicating success/failure and any error message
"""
temp_info = backup_info.split(",")
temp_ip = temp_info[0].split(":")

# Validate IP Address
temp_ipaddr = temp_ip[0].split(".")
if len(temp_ipaddr) < 4:
self.backup_error(f"Invalid IP Address: {temp_ip[0]}. Try again.")
return True, "", ""
for item in temp_ipaddr[0]:
if not item.isdigit():
if validate_ip_address(ip_address):

# Verify that the host IP is reachable:
self.display_message_box(
f"Pinging address {ip_address}. Please wait...",
True,
)
self.update() # Force a window refresh.

# Ping IP address.
response = os.system("ping -c 1 -t50 > /dev/null " + ip_address) # noqa: S605
if response != 0:
self.backup_error(
f"Invalid IP Address: {temp_ip[0]}. Try again.",
f"{ip_address} is not reachable (error {response}). Try again.",
)
return True, "", ""
# Verify that the host IP (temp_ip[0]) is reachable:
self.display_message_box(
f"Pinging address {temp_ip[0]}. Please wait...",
True,
)
self.update() # Force a window refresh.
# Ping IP address.
response = os.system("ping -c 1 -t50 > /dev/null " + temp_ip[0]) # noqa: S605
if response != 0:
return True
self.display_message_box(
"Ping successful.",
True,
)
else:
self.backup_error(
f"{temp_ip[0]} is not reachable (error {response}). Try again.",
f"Invalid IP address: {ip_address}. Try again.",
)
return True, "", ""
self.display_message_box(
"Ping successful.",
False,
)
return True

# Validate port number
if len(temp_ip) == 1 or not temp_ip[1].isdigit:
if validate_port(ip_address, port_number) != 0:
self.backup_error(
f"Invalid port number: {temp_ipaddr[1]}. Try again.",
f"Invalid Port number: {port_number}. Try again.",
)
return True, "", ""
return True

# Validate file location
if len(temp_info) < 2 or temp_info[1] == "":
if len(file_location) < 2 or file_location == "":
self.backup_error("File location is missing. Try again.")
return None

# All is well so far...
self.backup_file_http = temp_info[0]
self.backup_file_location = temp_info[1]
return True

# Empty message = good to go...no error.
self.backup_error("")
return False, self.backup_file_http, self.backup_file_location
return False


# ##################################################################################
# Clear all buttons associated with fetching the backup file from Android device
# ##################################################################################
def clear_android_buttons(self) -> None: # noqa: ANN001
"""
Clears android device configuration buttons and displays backup button
Args:
self: The class instance
Returns:
None
- Destroys IP, port, file entry and label widgets
- Destroys get backup button
- Displays new backup button with callback to get_backup_event method"""
with contextlib.suppress(AttributeError):
self.ip_entry.destroy()
self.port_entry.destroy()
self.file_entry.destroy()
self.ip_label.destroy()
self.port_label.destroy()
self.file_label.destroy()
self.get_backup_button.destroy()
self.cancel_entry_button.destroy()

self.display_backup_button("Get Backup from Android Device", "#246FB6", "#6563ff", self.get_backup_event)
7 changes: 4 additions & 3 deletions maptasker/src/initparg.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# preserved. Contributors provide an express grant of patent rights. #
# #
# #################################################################################### #
from maptasker.src.config import BACKUP_FILE_HTTP, BACKUP_FILE_LOCATION, OUTPUT_FONT
from maptasker.src.config import ANDROID_IPADDR, ANDROID_PORT, ANDROID_FILE, OUTPUT_FONT


#######################################################################################
Expand All @@ -26,9 +26,10 @@ def initialize_runtime_arguments() -> dict:
:return: runtime arguments in dictionary
"""
return {
"android_ipaddr": ANDROID_IPADDR, # IP address of Android device
"android_port": ANDROID_PORT, # Port of Android device
"android_file": ANDROID_FILE,
"appearance_mode": "system", # Appearance mode: "system", "dark", or "light"
"backup_file_http": BACKUP_FILE_HTTP, # Port for Android-based Tasker server, to get backup file from
"backup_file_location": BACKUP_FILE_LOCATION, # Location of the backup file to grab from Android device
"bold": False, # Display Project/Profile?Task/Scene names in bold text
"debug": False, # Run in debug mode (create log file)
"directory": False, # Display directory
Expand Down
Loading

0 comments on commit 88253a1

Please sign in to comment.