Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- """
- Garmin ConnectIQ Device Data Extractor
- This utility extracts information from Garmin ConnectIQ device definitions
- and outputs it in a tabular format.
- """
- import json
- import os
- import sys
- from pathlib import Path
- from typing import Dict, List, Optional, Any
- import argparse
- def extract_compiler_data(compiler_data: Dict[str, Any]) -> Dict[str, Any]:
- """Extract relevant data from compiler.json"""
- return {
- 'device_id': compiler_data.get('deviceId', ''),
- 'display_name': compiler_data.get('displayName', ''),
- 'display_type': compiler_data.get('displayType', ''),
- 'complication_icon_width': compiler_data.get('complicationIcon', {}).get('width', ''),
- 'complication_icon_height': compiler_data.get('complicationIcon', {}).get('height', ''),
- 'alpha_blending_support': compiler_data.get('alphaBlendingSupport', ''),
- 'enhanced_graphic_support': compiler_data.get('enhancedGraphicSupport', ''),
- 'screen_rotation_support': compiler_data.get('screenRotationSupport', ''),
- }
- def extract_simulator_data(simulator_data: Dict[str, Any]) -> Dict[str, Any]:
- """Extract relevant data from simulator.json"""
- display_info = simulator_data.get('display', {})
- menu2_info = simulator_data.get('layouts', [{}])[0].get('menu2', {}) if simulator_data.get('layouts') else {}
- glance_info = simulator_data.get('glance', {})
- # Extract menu2 icon dimensions
- menu2_icons = menu2_info.get('items', {}).get('icons', {})
- menu2_left_location = menu2_icons.get('leftLocation', {})
- menu2_right_location = menu2_icons.get('rightLocation', {})
- return {
- 'menu2_mode': menu2_info.get('mode', ''),
- 'menu2_title_height': menu2_info.get('title', {}).get('height', ''),
- 'menu2_title_width': menu2_info.get('title', {}).get('width', ''),
- 'menu2_icon_width': menu2_left_location.get('width', menu2_right_location.get('width', '')),
- 'menu2_icon_height': menu2_left_location.get('height', menu2_right_location.get('height', '')),
- 'glance_icon_width': glance_info.get('iconArea', {}).get('width', ''),
- 'glance_icon_height': glance_info.get('iconArea', {}).get('height', ''),
- 'glance_content_width': glance_info.get('contentArea', {}).get('width', ''),
- 'glance_content_height': glance_info.get('contentArea', {}).get('height', ''),
- 'app_storage_capacity': simulator_data.get('appStorageCapacity', ''),
- 'graphics_resource_pool_size': simulator_data.get('graphicsResourcePoolSize', ''),
- 'watchdog_count': simulator_data.get('watchdogCount', ''),
- }
- def process_device_directory(device_dir: Path) -> Optional[Dict[str, Any]]:
- """Process a single device directory and extract data"""
- compiler_json = device_dir / 'compiler.json'
- simulator_json = device_dir / 'simulator.json'
- if not compiler_json.exists() or not simulator_json.exists():
- return None
- try:
- with open(compiler_json, 'r') as f:
- compiler_data = json.load(f)
- with open(simulator_json, 'r') as f:
- simulator_data = json.load(f)
- device_info = {
- **extract_compiler_data(compiler_data),
- **extract_simulator_data(simulator_data)
- }
- return device_info
- except (json.JSONDecodeError, FileNotFoundError, KeyError) as e:
- print(f"Error processing {device_dir.name}: {e}", file=sys.stderr)
- return None
- def format_table_output(devices: List[Dict[str, Any]], output_format: str = 'table') -> str:
- """Format the device data as a table"""
- if not devices:
- return "No devices found."
- if output_format == 'csv':
- import csv
- import io
- output = io.StringIO()
- writer = csv.DictWriter(output, fieldnames=devices[0].keys())
- writer.writeheader()
- writer.writerows(devices)
- return output.getvalue()
- elif output_format == 'json':
- return json.dumps(devices, indent=2)
- else: # table format
- # Get column headers
- headers = list(devices[0].keys())
- # Calculate column widths
- col_widths = {}
- for header in headers:
- col_widths[header] = max(
- len(header),
- max(len(str(device.get(header, ''))) for device in devices)
- )
- # Create separator line
- separator = '+' + '+'.join('-' * (col_widths[h] + 2) for h in headers) + '+'
- # Format header row
- header_row = '|' + '|'.join(f" {h:<{col_widths[h]}} " for h in headers) + '|'
- # Format data rows
- data_rows = []
- for device in devices:
- row = '|' + '|'.join(f" {str(device.get(h, '')):<{col_widths[h]}} " for h in headers) + '|'
- data_rows.append(row)
- # Combine all parts
- return '\n'.join([separator, header_row, separator] + data_rows + [separator])
- def main():
- parser = argparse.ArgumentParser(description='Extract Garmin ConnectIQ device data')
- parser.add_argument('devices_dir',
- help='Path to Garmin ConnectIQ Devices directory',
- default='.',
- nargs='?')
- parser.add_argument('--format', '-f',
- choices=['table', 'csv', 'json'],
- default='table',
- help='Output format (default: table)')
- parser.add_argument('--filter', '-F',
- help='Filter devices by name pattern (case-insensitive)')
- parser.add_argument('--output', '-o',
- help='Output file (default: stdout)')
- args = parser.parse_args()
- devices_dir = Path(args.devices_dir)
- if not devices_dir.exists():
- print(f"Error: Directory {devices_dir} does not exist", file=sys.stderr)
- sys.exit(1)
- devices = []
- # Process each device directory
- for device_dir in sorted(devices_dir.iterdir()):
- if device_dir.is_dir():
- # Apply filter if specified
- if args.filter and args.filter.lower() not in device_dir.name.lower():
- continue
- device_info = process_device_directory(device_dir)
- if device_info:
- devices.append(device_info)
- if not devices:
- print("No valid device directories found.", file=sys.stderr)
- sys.exit(1)
- # Format and output the results
- output = format_table_output(devices, args.format)
- if args.output:
- with open(args.output, 'w') as f:
- f.write(output)
- print(f"Output written to {args.output}")
- else:
- print(output)
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment