| 
									
										
										
										
											2017-06-05 16:02:39 +03:00
										 |  |  | # Copyright (c) 2014-present PlatformIO <contact@platformio.org> | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | # | 
					
						
							|  |  |  | # Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | # you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | # You may obtain a copy of the License at | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #    http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | # distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | # See the License for the specific language governing permissions and | 
					
						
							|  |  |  | # limitations under the License. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | import sys | 
					
						
							|  |  |  | import threading | 
					
						
							|  |  |  | from tempfile import mkdtemp | 
					
						
							|  |  |  | from time import sleep | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import click | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 19:44:37 +03:00
										 |  |  | from platformio import exception, fs | 
					
						
							| 
									
										
										
										
											2020-03-12 14:28:54 +02:00
										 |  |  | from platformio.commands.device import helpers as device_helpers | 
					
						
							|  |  |  | from platformio.commands.device.command import device_monitor as cmd_device_monitor | 
					
						
							| 
									
										
										
										
											2017-03-11 23:28:55 +02:00
										 |  |  | from platformio.managers.core import pioplus_call | 
					
						
							| 
									
										
										
										
											2019-11-28 16:15:54 +02:00
										 |  |  | from platformio.project.exception import NotPlatformIOProjectError | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | # pylint: disable=unused-argument | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @click.group("remote", short_help="PIO Remote") | 
					
						
							| 
									
										
										
										
											2016-10-04 01:24:38 +03:00
										 |  |  | @click.option("-a", "--agent", multiple=True) | 
					
						
							|  |  |  | def cli(**kwargs): | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 01:24:38 +03:00
										 |  |  | @cli.group("agent", short_help="Start new agent or list active") | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | def remote_agent(): | 
					
						
							| 
									
										
										
										
											2016-10-04 01:24:38 +03:00
										 |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @remote_agent.command("start", short_help="Start agent") | 
					
						
							|  |  |  | @click.option("-n", "--name") | 
					
						
							| 
									
										
										
										
											2016-10-04 19:37:48 +03:00
										 |  |  | @click.option("-s", "--share", multiple=True, metavar="E-MAIL") | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "-d", | 
					
						
							|  |  |  |     "--working-dir", | 
					
						
							|  |  |  |     envvar="PLATFORMIO_REMOTE_AGENT_DIR", | 
					
						
							|  |  |  |     type=click.Path(file_okay=False, dir_okay=True, writable=True, resolve_path=True), | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-10-04 01:24:38 +03:00
										 |  |  | def remote_agent_start(**kwargs): | 
					
						
							|  |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 00:28:49 +02:00
										 |  |  | @remote_agent.command("reload", short_help="Reload agents") | 
					
						
							|  |  |  | def remote_agent_reload(): | 
					
						
							|  |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 01:24:38 +03:00
										 |  |  | @remote_agent.command("list", short_help="List active agents") | 
					
						
							|  |  |  | def remote_agent_list(): | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @cli.command("update", short_help="Update installed Platforms, Packages and Libraries") | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "-c", | 
					
						
							|  |  |  |     "--only-check", | 
					
						
							|  |  |  |     is_flag=True, | 
					
						
							|  |  |  |     help="DEPRECATED. Please use `--dry-run` instead", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--dry-run", is_flag=True, help="Do not update, only check for the new versions" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2019-05-16 20:02:45 +03:00
										 |  |  | def remote_update(only_check, dry_run): | 
					
						
							| 
									
										
										
										
											2016-11-12 00:28:49 +02:00
										 |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:24:52 +02:00
										 |  |  | @cli.command("run", short_help="Process project environments remotely") | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | @click.option("-e", "--environment", multiple=True) | 
					
						
							|  |  |  | @click.option("-t", "--target", multiple=True) | 
					
						
							|  |  |  | @click.option("--upload-port") | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "-d", | 
					
						
							|  |  |  |     "--project-dir", | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |     default=os.getcwd, | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  |     type=click.Path( | 
					
						
							|  |  |  |         exists=True, file_okay=True, dir_okay=True, writable=True, resolve_path=True | 
					
						
							|  |  |  |     ), | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-11-02 18:24:52 +02:00
										 |  |  | @click.option("--disable-auto-clean", is_flag=True) | 
					
						
							| 
									
										
										
										
											2016-11-26 22:59:22 +02:00
										 |  |  | @click.option("-r", "--force-remote", is_flag=True) | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | @click.option("-s", "--silent", is_flag=True) | 
					
						
							|  |  |  | @click.option("-v", "--verbose", is_flag=True) | 
					
						
							|  |  |  | def remote_run(**kwargs): | 
					
						
							|  |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:24:52 +02:00
										 |  |  | @cli.command("test", short_help="Remote Unit Testing") | 
					
						
							|  |  |  | @click.option("--environment", "-e", multiple=True, metavar="<environment>") | 
					
						
							|  |  |  | @click.option("--ignore", "-i", multiple=True, metavar="<pattern>") | 
					
						
							|  |  |  | @click.option("--upload-port") | 
					
						
							|  |  |  | @click.option("--test-port") | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "-d", | 
					
						
							|  |  |  |     "--project-dir", | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |     default=os.getcwd, | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  |     type=click.Path( | 
					
						
							|  |  |  |         exists=True, file_okay=False, dir_okay=True, writable=True, resolve_path=True | 
					
						
							|  |  |  |     ), | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-11-26 22:59:22 +02:00
										 |  |  | @click.option("-r", "--force-remote", is_flag=True) | 
					
						
							| 
									
										
										
										
											2016-11-02 18:24:52 +02:00
										 |  |  | @click.option("--without-building", is_flag=True) | 
					
						
							|  |  |  | @click.option("--without-uploading", is_flag=True) | 
					
						
							|  |  |  | @click.option("--verbose", "-v", is_flag=True) | 
					
						
							|  |  |  | def remote_test(**kwargs): | 
					
						
							|  |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @cli.group("device", short_help="Monitor remote device or list existing") | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | def remote_device(): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:24:52 +02:00
										 |  |  | @remote_device.command("list", short_help="List remote devices") | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  | @click.option("--json-output", is_flag=True) | 
					
						
							|  |  |  | def device_list(json_output): | 
					
						
							|  |  |  |     pioplus_call(sys.argv[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 18:24:52 +02:00
										 |  |  | @remote_device.command("monitor", short_help="Monitor remote device") | 
					
						
							| 
									
										
										
										
											2016-10-31 18:13:41 +02:00
										 |  |  | @click.option("--port", "-p", help="Port, a number or a device name") | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  | @click.option("--baud", "-b", type=int, help="Set baud rate, default=9600") | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "--parity", | 
					
						
							|  |  |  |     default="N", | 
					
						
							|  |  |  |     type=click.Choice(["N", "E", "O", "S", "M"]), | 
					
						
							|  |  |  |     help="Set parity, default=N", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option("--rtscts", is_flag=True, help="Enable RTS/CTS flow control, default=Off") | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--xonxoff", is_flag=True, help="Enable software flow control, default=Off" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--rts", default=None, type=click.IntRange(0, 1), help="Set initial RTS line state" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--dtr", default=None, type=click.IntRange(0, 1), help="Set initial DTR line state" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-10-31 18:13:41 +02:00
										 |  |  | @click.option("--echo", is_flag=True, help="Enable local echo, default=Off") | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "--encoding", | 
					
						
							|  |  |  |     default="UTF-8", | 
					
						
							|  |  |  |     help="Set the encoding for the serial port (e.g. hexlify, " | 
					
						
							|  |  |  |     "Latin1, UTF-8), default: UTF-8", | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-10-31 18:13:41 +02:00
										 |  |  | @click.option("--filter", "-f", multiple=True, help="Add text transformation") | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "--eol", | 
					
						
							|  |  |  |     default="CRLF", | 
					
						
							|  |  |  |     type=click.Choice(["CR", "LF", "CRLF"]), | 
					
						
							|  |  |  |     help="End of line mode, default=CRLF", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option("--raw", is_flag=True, help="Do not apply any encodings/transformations") | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--exit-char", | 
					
						
							|  |  |  |     type=int, | 
					
						
							|  |  |  |     default=3, | 
					
						
							|  |  |  |     help="ASCII code of special character that is used to exit " | 
					
						
							|  |  |  |     "the application, default=3 (Ctrl+C)", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--menu-char", | 
					
						
							|  |  |  |     type=int, | 
					
						
							|  |  |  |     default=20, | 
					
						
							|  |  |  |     help="ASCII code of special character that is used to " | 
					
						
							|  |  |  |     "control miniterm (menu), default=20 (DEC)", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "--quiet", | 
					
						
							|  |  |  |     is_flag=True, | 
					
						
							|  |  |  |     help="Diagnostics: suppress non-error messages, default=Off", | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  | @click.option( | 
					
						
							|  |  |  |     "-d", | 
					
						
							|  |  |  |     "--project-dir", | 
					
						
							|  |  |  |     default=os.getcwd, | 
					
						
							|  |  |  |     type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True), | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | @click.option( | 
					
						
							|  |  |  |     "-e", | 
					
						
							|  |  |  |     "--environment", | 
					
						
							|  |  |  |     help="Load configuration from `platformio.ini` and specified environment", | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-10-31 18:13:41 +02:00
										 |  |  | @click.pass_context | 
					
						
							|  |  |  | def device_monitor(ctx, **kwargs): | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |     project_options = {} | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         with fs.cd(kwargs["project_dir"]): | 
					
						
							| 
									
										
										
										
											2020-03-12 14:28:54 +02:00
										 |  |  |             project_options = device_helpers.get_project_options(kwargs["environment"]) | 
					
						
							|  |  |  |         kwargs = device_helpers.apply_project_monitor_options(kwargs, project_options) | 
					
						
							| 
									
										
										
										
											2019-11-28 16:15:54 +02:00
										 |  |  |     except NotPlatformIOProjectError: | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwargs["baud"] = kwargs["baud"] or 9600 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 21:43:28 +03:00
										 |  |  |     def _tx_target(sock_dir): | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |         pioplus_argv = ["remote", "device", "monitor"] | 
					
						
							| 
									
										
										
										
											2020-03-12 14:28:54 +02:00
										 |  |  |         pioplus_argv.extend(device_helpers.options_to_argv(kwargs, project_options)) | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |         pioplus_argv.extend(["--sock", sock_dir]) | 
					
						
							| 
									
										
										
										
											2016-10-05 21:43:28 +03:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |             pioplus_call(pioplus_argv) | 
					
						
							| 
									
										
										
										
											2016-10-05 21:43:28 +03:00
										 |  |  |         except exception.ReturnErrorCode: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |     sock_dir = mkdtemp(suffix="pioplus") | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |     sock_file = os.path.join(sock_dir, "sock") | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2019-09-23 23:13:48 +03:00
										 |  |  |         t = threading.Thread(target=_tx_target, args=(sock_dir,)) | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |         t.start() | 
					
						
							| 
									
										
										
										
											2019-11-11 22:38:16 +02:00
										 |  |  |         while t.is_alive() and not os.path.isfile(sock_file): | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |             sleep(0.1) | 
					
						
							|  |  |  |         if not t.is_alive(): | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2020-03-05 23:52:13 +02:00
										 |  |  |         with open(sock_file) as fp: | 
					
						
							|  |  |  |             kwargs["port"] = fp.read() | 
					
						
							| 
									
										
										
										
											2020-03-12 14:28:54 +02:00
										 |  |  |         ctx.invoke(cmd_device_monitor, **kwargs) | 
					
						
							| 
									
										
										
										
											2016-09-26 22:15:08 +03:00
										 |  |  |         t.join(2) | 
					
						
							|  |  |  |     finally: | 
					
						
							| 
									
										
										
										
											2019-08-12 19:44:37 +03:00
										 |  |  |         fs.rmtree(sock_dir) |