├── .gitignore ├── LICENSE ├── README.md └── saleae_cli.py /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/settings.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Saleae 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-saleae-cli 2 | This is a basic command line utility to automate the Saleae Logic software. 3 | 4 | This tool can be used to automatically take a series of shorter captures over an extended time period. For example, if a 24 hour capture can't be recorded in a single run due to memory limitations, this utility could be used to automatically take 24 captures of one hour each. 5 | 6 | ### Prerequisites 7 | - Saleae Logic software running with the socket API enabled. [instructions](https://support.saleae.com/saleae-api-and-sdk/socket-api#enable-the-logic-software-for-scripting) 8 | - [python 3](https://www.python.org/downloads/) installed. 9 | - [ppannuto python-saleae](https://github.com/ppannuto/python-saleae) library installed. 10 | 11 | ### Usage 12 | 13 | The utility allows the user to set the number of captures and the duration of each capture. It also optionally supports three different save operations: 14 | 1. save captures. If the `--save-captures` option is used, the utility will save each capture to the folder specified with the filename `N.logicdata`, where N is the index of the capture. 15 | 2. export captures. If the `--export-data` option is used, the utility will export each capture to the folder specified using the default csv export options provided by the [ppannuto python-saleae](https://github.com/ppannuto/python-saleae) library (thanks for that feature!) 16 | 3. export analyzers. If the `--export-analyzers` option is used, the utility will export each of the analyzers that are currently active in the capture to the specified folder. They will be named with the format `N_Analyzer Name.csv`, where N is the index of the capture and `Analyzer Name` is the user editable analyzer name in the software. 17 | 18 | ### Examples 19 | 20 | **Just take 5 captures, each 0.1 seconds long, without saving anything.** 21 | ``` 22 | python saleae_cli.py --capture-count 5 --capture-duration 0.1 23 | ``` 24 | Note: if python 2 and python 3 are installed, you may need to call python using `python3` 25 | 26 | **Take 24 captures, each 1 hour long, exporting the analyzers to an 'export' folder on the desktop.** 27 | 28 | Note that the destination folder must already exist before running the utility. 29 | 30 | (Windows) 31 | ``` 32 | python saleae_cli.py --capture-count 24 --capture-duration 3600 --export-analyzers \Users\\Desktop\export 33 | ``` 34 | (Linux or MacOS) 35 | ``` 36 | python saleae_cli.py --capture-count 24 --capture-duration 3600 --export-analyzers ~/Desktop/export 37 | ``` 38 | **Take 100 captures, each 10 seconds long, saving all outputs to the same 'export' folder on the desktop** 39 | 40 | (Windows) 41 | ``` 42 | python saleae_cli.py --capture-count 100 --capture-duration 10 --save-captures \Users\\Desktop\export --export-analyzers \Users\\Desktop\export --export-data \Users\\Desktop\export 43 | ``` 44 | (Linux or MacOS) 45 | ``` 46 | python saleae_cli.py --capture-count 3 --capture-duration 0.1 --save-captures ~/Desktop/export --export-analyzers ~/Desktop/export --export-data ~/Desktop/export 47 | ``` 48 | 49 | 50 | 51 | **Print out the CLI help** 52 | 53 | `python saleae_cli.py --help` 54 | 55 | ``` 56 | Saleae Command Line Interface Capture Utility 57 | 58 | optional arguments: 59 | -h, --help show this help message and exit 60 | --capture-count COUNT 61 | number of captures to repeat 62 | --capture-duration SECONDS 63 | duration of each capture in seconds 64 | --save-captures PATH if specified, saves each capture to the specified 65 | directory 66 | --export-data PATH if specified, exports the raw capture to the sepcified 67 | directory 68 | --export-analyzers PATH 69 | if specified, exports each analyzer to the specified 70 | directory 71 | --ip IP optional, IP address to connect to. Default localhost 72 | --port PORT optional, Port to connect to. Default 10429 73 | ``` 74 | -------------------------------------------------------------------------------- /saleae_cli.py: -------------------------------------------------------------------------------- 1 | import os 2 | import saleae 3 | import argparse 4 | 5 | def validate_path( path, argument_name ): 6 | if path != None: 7 | if os.path.isdir(path) == False: 8 | print('the specified ' + argument_name + ' directory does not exist or is invalid') 9 | print('you specified: ' + path) 10 | quit() 11 | 12 | parser = argparse.ArgumentParser(description='Saleae Command Line Interface Capture Utility') 13 | parser.add_argument('--capture-count', required=True, type=int, metavar='COUNT', help='number of captures to repeat') 14 | parser.add_argument('--capture-duration', required=True, type=float, metavar='SECONDS', help='duration of each capture in seconds') 15 | parser.add_argument('--save-captures', metavar='PATH', help='if specified, saves each capture to the specified directory') 16 | parser.add_argument('--export-data', metavar='PATH', help='if specified, exports the raw capture to the sepcified directory') 17 | parser.add_argument('--export-analyzers', metavar='PATH', help='if specified, exports each analyzer to the specified directory') 18 | parser.add_argument('--ip', metavar='IP', default='localhost', help='optional, IP address to connect to. Default localhost') 19 | parser.add_argument('--port', metavar='PORT', default=10429, help='optional, Port to connect to. Default 10429') 20 | parser.add_argument('--exit', action='store_true', help='optional, use to close the Logic software once complete') 21 | 22 | args = parser.parse_args() 23 | 24 | validate_path(args.save_captures, '--save-captures') 25 | validate_path(args.export_data, '--export-data') 26 | validate_path(args.export_analyzers, '--export-analyzers') 27 | 28 | 29 | s = saleae.Saleae(args.ip, args.port) 30 | 31 | for x in range(args.capture_count): 32 | #set capture duration 33 | s.set_capture_seconds(args.capture_duration) 34 | #start capture. Only save to disk if the --save-captures option was specified. 35 | if args.save_captures != None: 36 | file_name = '{0}.logicdata'.format(x) 37 | save_path = os.path.join(args.save_captures, file_name) 38 | print('starting capture and saving to ' + save_path) 39 | s.capture_to_file(save_path) 40 | else: 41 | #currently, the python library doesn't provide a CAPTURE command that blocks until an ACK is received 42 | s._cmd('CAPTURE') 43 | 44 | #raw export 45 | if args.export_data != None: 46 | file_name = '{0}.csv'.format(x) 47 | save_path = os.path.join(args.export_data, file_name) 48 | print('exporting data to ' + save_path) 49 | s.export_data2(save_path) 50 | 51 | #analyzer export 52 | if args.export_analyzers != None: 53 | analyzers = s.get_analyzers() 54 | if analyzers.count == 0: 55 | print('Warning: analyzer export path was specified, but no analyzers are present in the capture') 56 | for analyzer in analyzers: 57 | file_name = '{0}_{1}.csv'.format(x, analyzer[0]) 58 | save_path = os.path.join(args.export_analyzers, file_name) 59 | print('exporting analyzer ' + analyzer[0] + ' to ' + save_path) 60 | s.export_analyzer(analyzer[1], save_path) 61 | 62 | if args.exit is True: 63 | print('closing Logic software') 64 | try: 65 | s.exit() 66 | except: 67 | # ignore errors from exit command, since it will raise due to socket disconnect. 68 | pass --------------------------------------------------------------------------------