runfap.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/env python3
  2. from flipper.app import App
  3. from flipper.storage import FlipperStorage, FlipperStorageOperations
  4. from flipper.utils.cdc import resolve_port
  5. import os
  6. import posixpath
  7. from functools import reduce
  8. import operator
  9. class Main(App):
  10. def init(self):
  11. self.parser.add_argument("-p", "--port", help="CDC Port", default="auto")
  12. self.parser.add_argument(
  13. "--sources",
  14. "-s",
  15. nargs="+",
  16. action="append",
  17. default=[],
  18. help="Files to send",
  19. )
  20. self.parser.add_argument(
  21. "--targets",
  22. "-t",
  23. nargs="+",
  24. action="append",
  25. default=[],
  26. help="File destinations (must be same length as -s)",
  27. )
  28. self.parser.add_argument(
  29. "--host-app",
  30. "-a",
  31. help="Host app to launch",
  32. )
  33. self.parser.set_defaults(func=self.install)
  34. @staticmethod
  35. def flatten(l):
  36. return reduce(operator.concat, l, [])
  37. def install(self):
  38. self.args.sources = self.flatten(self.args.sources)
  39. self.args.targets = self.flatten(self.args.targets)
  40. if len(self.args.sources) != len(self.args.targets):
  41. self.logger.error(
  42. f"Error: sources ({self.args.sources}) and targets ({self.args.targets}) must be same length"
  43. )
  44. return 1
  45. if not (port := resolve_port(self.logger, self.args.port)):
  46. return 2
  47. try:
  48. with FlipperStorage(port) as storage:
  49. storage_ops = FlipperStorageOperations(storage)
  50. for fap_local_path, fap_dst_path in zip(
  51. self.args.sources, self.args.targets
  52. ):
  53. self.logger.info(f'Installing "{fap_local_path}" to {fap_dst_path}')
  54. storage_ops.recursive_send(fap_dst_path, fap_local_path, False)
  55. fap_host_app = self.args.targets[0]
  56. startup_command = f'"Applications" {fap_host_app}'
  57. if self.args.host_app:
  58. startup_command = self.args.host_app
  59. self.logger.info(f"Launching app: {startup_command}")
  60. storage.send_and_wait_eol(f"loader open {startup_command}\r")
  61. if len(result := storage.read.until(storage.CLI_EOL)):
  62. self.logger.error(f"Unexpected response: {result.decode('ascii')}")
  63. return 3
  64. return 0
  65. except Exception as e:
  66. self.logger.error(f"Error: {e}")
  67. # raise
  68. return 4
  69. if __name__ == "__main__":
  70. Main()()