This commit is contained in:
Jonas Zeunert
2024-08-16 21:57:55 +02:00
parent adeb5c5ec7
commit 4309a2d185
1696 changed files with 279655 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

87
code/.venv/bin/activate Normal file
View File

@@ -0,0 +1,87 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
if [ "${BASH_SOURCE-}" = "$0" ]; then
echo "You must source this script: \$ source $0" >&2
exit 33
fi
deactivate () {
unset -f pydoc >/dev/null 2>&1 || true
# reset old environment variables
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# The hash command must be called to get it to forget past
# commands. Without forgetting past commands the $PATH changes
# we made may not be respected
hash -r 2>/dev/null
if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
unset VIRTUAL_ENV_PROMPT
if [ ! "${1-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV='/home/rhetenor/Projects/esp/python/.venv'
if ([ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]) && $(command -v cygpath &> /dev/null) ; then
VIRTUAL_ENV=$(cygpath -u "$VIRTUAL_ENV")
fi
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
if [ "x" != x ] ; then
VIRTUAL_ENV_PROMPT=""
else
VIRTUAL_ENV_PROMPT=$(basename "$VIRTUAL_ENV")
fi
export VIRTUAL_ENV_PROMPT
# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1-}"
PS1="(${VIRTUAL_ENV_PROMPT}) ${PS1-}"
export PS1
fi
# Make sure to unalias pydoc if it's already there
alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true
pydoc () {
python -m pydoc "$@"
}
# The hash command must be called to get it to forget past
# commands. Without forgetting past commands the $PATH changes
# we made may not be respected
hash -r 2>/dev/null || true

View File

@@ -0,0 +1,55 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
set newline='\
'
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV '/home/rhetenor/Projects/esp/python/.venv'
set _OLD_VIRTUAL_PATH="$PATH:q"
setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q"
if ('' != "") then
setenv VIRTUAL_ENV_PROMPT ''
else
setenv VIRTUAL_ENV_PROMPT "$VIRTUAL_ENV:t:q"
endif
if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then
if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then
set do_prompt = "1"
else
set do_prompt = "0"
endif
else
set do_prompt = "1"
endif
if ( $do_prompt == "1" ) then
# Could be in a non-interactive environment,
# in which case, $prompt is undefined and we wouldn't
# care about the prompt anyway.
if ( $?prompt ) then
set _OLD_VIRTUAL_PROMPT="$prompt:q"
if ( "$prompt:q" =~ *"$newline:q"* ) then
:
else
set prompt = '('"$VIRTUAL_ENV_PROMPT:q"') '"$prompt:q"
endif
endif
endif
unset env_name
unset do_prompt
alias pydoc python -m pydoc
rehash

View File

@@ -0,0 +1,103 @@
# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*.
# Do not run it directly.
function _bashify_path -d "Converts a fish path to something bash can recognize"
set fishy_path $argv
set bashy_path $fishy_path[1]
for path_part in $fishy_path[2..-1]
set bashy_path "$bashy_path:$path_part"
end
echo $bashy_path
end
function _fishify_path -d "Converts a bash path to something fish can recognize"
echo $argv | tr ':' '\n'
end
function deactivate -d 'Exit virtualenv mode and return to the normal environment.'
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling
if test (echo $FISH_VERSION | head -c 1) -lt 3
set -gx PATH (_fishify_path "$_OLD_VIRTUAL_PATH")
else
set -gx PATH $_OLD_VIRTUAL_PATH
end
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME "$_OLD_VIRTUAL_PYTHONHOME"
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
and functions -q _old_fish_prompt
# Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`.
set -l fish_function_path
# Erase virtualenv's `fish_prompt` and restore the original.
functions -e fish_prompt
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
end
set -e VIRTUAL_ENV
set -e VIRTUAL_ENV_PROMPT
if test "$argv[1]" != 'nondestructive'
# Self-destruct!
functions -e pydoc
functions -e deactivate
functions -e _bashify_path
functions -e _fishify_path
end
end
# Unset irrelevant variables.
deactivate nondestructive
set -gx VIRTUAL_ENV '/home/rhetenor/Projects/esp/python/.venv'
# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling
if test (echo $FISH_VERSION | head -c 1) -lt 3
set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH)
else
set -gx _OLD_VIRTUAL_PATH $PATH
end
set -gx PATH "$VIRTUAL_ENV"'/bin' $PATH
# Prompt override provided?
# If not, just use the environment name.
if test -n ''
set -gx VIRTUAL_ENV_PROMPT ''
else
set -gx VIRTUAL_ENV_PROMPT (basename "$VIRTUAL_ENV")
end
# Unset `$PYTHONHOME` if set.
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
function pydoc
python -m pydoc $argv
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# Copy the current `fish_prompt` function as `_old_fish_prompt`.
functions -c fish_prompt _old_fish_prompt
function fish_prompt
# Run the user's prompt first; it might depend on (pipe)status.
set -l prompt (_old_fish_prompt)
printf '(%s) ' $VIRTUAL_ENV_PROMPT
string join -- \n $prompt # handle multi-line prompts
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

View File

@@ -0,0 +1,96 @@
# virtualenv activation module
# Activate with `overlay use activate.nu`
# Deactivate with `deactivate`, as usual
#
# To customize the overlay name, you can call `overlay use activate.nu as foo`,
# but then simply `deactivate` won't work because it is just an alias to hide
# the "activate" overlay. You'd need to call `overlay hide foo` manually.
export-env {
def is-string [x] {
($x | describe) == 'string'
}
def has-env [...names] {
$names | each {|n|
$n in $env
} | all {|i| $i == true}
}
# Emulates a `test -z`, but btter as it handles e.g 'false'
def is-env-true [name: string] {
if (has-env $name) {
# Try to parse 'true', '0', '1', and fail if not convertible
let parsed = (do -i { $env | get $name | into bool })
if ($parsed | describe) == 'bool' {
$parsed
} else {
not ($env | get -i $name | is-empty)
}
} else {
false
}
}
let virtual_env = '/home/rhetenor/Projects/esp/python/.venv'
let bin = 'bin'
let is_windows = ($nu.os-info.family) == 'windows'
let path_name = (if (has-env 'Path') {
'Path'
} else {
'PATH'
}
)
let venv_path = ([$virtual_env $bin] | path join)
let new_path = ($env | get $path_name | prepend $venv_path)
# If there is no default prompt, then use the env name instead
let virtual_env_prompt = (if ('' | is-empty) {
($virtual_env | path basename)
} else {
''
})
let new_env = {
$path_name : $new_path
VIRTUAL_ENV : $virtual_env
VIRTUAL_ENV_PROMPT : $virtual_env_prompt
}
let new_env = (if (is-env-true 'VIRTUAL_ENV_DISABLE_PROMPT') {
$new_env
} else {
# Creating the new prompt for the session
let virtual_prefix = $'(char lparen)($virtual_env_prompt)(char rparen) '
# Back up the old prompt builder
let old_prompt_command = (if (has-env 'PROMPT_COMMAND') {
$env.PROMPT_COMMAND
} else {
''
})
let new_prompt = (if (has-env 'PROMPT_COMMAND') {
if 'closure' in ($old_prompt_command | describe) {
{|| $'($virtual_prefix)(do $old_prompt_command)' }
} else {
{|| $'($virtual_prefix)($old_prompt_command)' }
}
} else {
{|| $'($virtual_prefix)' }
})
$new_env | merge {
PROMPT_COMMAND : $new_prompt
VIRTUAL_PREFIX : $virtual_prefix
}
})
# Environment variables that will be loaded as the virtual env
load-env $new_env
}
export alias pydoc = python -m pydoc
export alias deactivate = overlay hide activate

View File

@@ -0,0 +1,61 @@
$script:THIS_PATH = $myinvocation.mycommand.path
$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
function global:deactivate([switch] $NonDestructive) {
if (Test-Path variable:_OLD_VIRTUAL_PATH) {
$env:PATH = $variable:_OLD_VIRTUAL_PATH
Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
}
if (Test-Path function:_old_virtual_prompt) {
$function:prompt = $function:_old_virtual_prompt
Remove-Item function:\_old_virtual_prompt
}
if ($env:VIRTUAL_ENV) {
Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
}
if ($env:VIRTUAL_ENV_PROMPT) {
Remove-Item env:VIRTUAL_ENV_PROMPT -ErrorAction SilentlyContinue
}
if (!$NonDestructive) {
# Self destruct!
Remove-Item function:deactivate
Remove-Item function:pydoc
}
}
function global:pydoc {
python -m pydoc $args
}
# unset irrelevant variables
deactivate -nondestructive
$VIRTUAL_ENV = $BASE_DIR
$env:VIRTUAL_ENV = $VIRTUAL_ENV
if ("" -ne "") {
$env:VIRTUAL_ENV_PROMPT = ""
}
else {
$env:VIRTUAL_ENV_PROMPT = $( Split-Path $env:VIRTUAL_ENV -Leaf )
}
New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH
if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
function global:_old_virtual_prompt {
""
}
$function:_old_virtual_prompt = $function:prompt
function global:prompt {
# Add the custom prefix to the existing prompt
$previous_prompt_value = & $function:_old_virtual_prompt
("(" + $env:VIRTUAL_ENV_PROMPT + ") " + $previous_prompt_value)
}
}

View File

@@ -0,0 +1,38 @@
"""
Activate virtualenv for current interpreter:
import runpy
runpy.run_path(this_file)
This can be used when you must use an existing Python interpreter, not the virtualenv bin/python.
""" # noqa: D415
from __future__ import annotations
import os
import site
import sys
try:
abs_file = os.path.abspath(__file__)
except NameError as exc:
msg = "You must use import runpy; runpy.run_path(this_file)"
raise AssertionError(msg) from exc
bin_dir = os.path.dirname(abs_file)
base = bin_dir[: -len("bin") - 1] # strip away the bin part from the __file__, plus the path separator
# prepend bin to PATH (this file is inside the bin directory)
os.environ["PATH"] = os.pathsep.join([bin_dir, *os.environ.get("PATH", "").split(os.pathsep)])
os.environ["VIRTUAL_ENV"] = base # virtual env is right above bin directory
os.environ["VIRTUAL_ENV_PROMPT"] = "" or os.path.basename(base) # noqa: SIM222
# add the virtual environments libraries to the host python import mechanism
prev_length = len(sys.path)
for lib in "../lib/python3.12/site-packages".split(os.pathsep):
path = os.path.realpath(os.path.join(bin_dir, lib))
site.addsitedir(path.decode("utf-8") if "" else path)
sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]
sys.real_prefix = sys.prefix
sys.prefix = base

115
code/.venv/bin/bin2hex.py Executable file
View File

@@ -0,0 +1,115 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# Copyright (c) 2008-2018 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''Intel HEX file format bin2hex convertor utility.'''
VERSION = '2.3.0'
if __name__ == '__main__':
import getopt
import os
import sys
usage = '''Bin2Hex convertor utility.
Usage:
python bin2hex.py [options] INFILE [OUTFILE]
Arguments:
INFILE name of bin file for processing.
Use '-' for reading from stdin.
OUTFILE name of output file. If omitted then output
will be writing to stdout.
Options:
-h, --help this help message.
-v, --version version info.
--offset=N offset for loading bin file (default: 0).
'''
offset = 0
try:
opts, args = getopt.getopt(sys.argv[1:], "hv",
["help", "version", "offset="])
for o, a in opts:
if o in ("-h", "--help"):
print(usage)
sys.exit(0)
elif o in ("-v", "--version"):
print(VERSION)
sys.exit(0)
elif o in ("--offset"):
base = 10
if a[:2].lower() == '0x':
base = 16
try:
offset = int(a, base)
except:
raise getopt.GetoptError('Bad offset value')
if not args:
raise getopt.GetoptError('Input file is not specified')
if len(args) > 2:
raise getopt.GetoptError('Too many arguments')
except getopt.GetoptError:
msg = sys.exc_info()[1] # current exception
txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool
print(txt)
print(usage)
sys.exit(2)
from intelhex import compat
fin = args[0]
if fin == '-':
# read from stdin
fin = compat.get_binary_stdin()
elif not os.path.isfile(fin):
txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool
print(txt)
sys.exit(1)
if len(args) == 2:
fout = args[1]
else:
# write to stdout
fout = sys.stdout # compat.get_binary_stdout()
from intelhex import bin2hex
sys.exit(bin2hex(fin, fout, offset))

View File

@@ -0,0 +1,311 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# SPDX-FileCopyrightText: 2009-2015 Chris Liechti
# SPDX-FileContributor: 2020-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: BSD-3-Clause
#
# Redirect data from a TCP/IP connection to a serial port and vice versa using RFC 2217.
#
# This is a modified version of rfc2217_server.py provided by the pyserial package
# (pythonhosted.org/pyserial/examples.html#single-port-tcp-ip-serial-bridge-rfc-2217).
# It uses a custom PortManager to properly apply the RTS & DTR signals
# for reseting ESP chips.
#
# Run the following command on the server side to make
# connection between /dev/ttyUSB1 and TCP port 4000:
#
# python esp_rfc2217_server.py -p 4000 /dev/ttyUSB1
#
# Esptool can connect to the ESP device through that server as it is
# demonstrated in the following example:
#
# esptool.py --port rfc2217://localhost:4000?ign_set_control flash_id
#
###################################################################################
# redirect data from a TCP/IP connection to a serial port and vice versa
# using RFC 2217
#
# (C) 2009-2015 Chris Liechti <cliechti@gmx.net>
#
# SPDX-License-Identifier: BSD-3-Clause
import logging
import os
import socket
import sys
import threading
import time
from esptool.config import load_config_file
from esptool.reset import (
ClassicReset,
CustomReset,
DEFAULT_RESET_DELAY,
HardReset,
UnixTightReset,
)
import serial
import serial.rfc2217
from serial.rfc2217 import (
COM_PORT_OPTION,
SET_CONTROL,
SET_CONTROL_DTR_OFF,
SET_CONTROL_DTR_ON,
SET_CONTROL_RTS_OFF,
SET_CONTROL_RTS_ON,
)
cfg, _ = load_config_file(verbose=True)
cfg = cfg["esptool"]
class EspPortManager(serial.rfc2217.PortManager):
"""
The beginning of the reset sequence is detected and the proper reset sequence
is applied in a thread. The rest of the reset sequence received is just ignored
and not sent to the serial port.
"""
def __init__(self, serial_port, connection, esp32r0_delay, logger=None):
self.esp32r0_delay = esp32r0_delay
self.is_download_mode = False
super(EspPortManager, self).__init__(serial_port, connection, logger)
def _telnet_process_subnegotiation(self, suboption):
if suboption[0:1] == COM_PORT_OPTION and suboption[1:2] == SET_CONTROL:
if suboption[2:3] == SET_CONTROL_DTR_OFF:
self.is_download_mode = False
self.serial.dtr = False
return
elif suboption[2:3] == SET_CONTROL_RTS_OFF and not self.is_download_mode:
reset_thread = threading.Thread(target=self._hard_reset_thread)
reset_thread.daemon = True
reset_thread.name = "hard_reset_thread"
reset_thread.start()
return
elif suboption[2:3] == SET_CONTROL_DTR_ON and not self.is_download_mode:
self.is_download_mode = True
reset_thread = threading.Thread(target=self._reset_thread)
reset_thread.daemon = True
reset_thread.name = "reset_thread"
reset_thread.start()
return
elif suboption[2:3] in [
SET_CONTROL_DTR_ON,
SET_CONTROL_RTS_ON,
SET_CONTROL_RTS_OFF,
]:
return
# only in cases not handled above do the original implementation in PortManager
super(EspPortManager, self)._telnet_process_subnegotiation(suboption)
def _hard_reset_thread(self):
"""
The reset logic used for hard resetting the chip.
"""
if self.logger:
self.logger.info("Activating hard reset in thread")
HardReset(self.serial)()
def _reset_thread(self):
"""
The reset logic is used from esptool.py because the RTS and DTR signals
cannot be retransmitted through RFC 2217 with proper timing.
"""
if self.logger:
self.logger.info("Activating reset in thread")
delay = DEFAULT_RESET_DELAY
if self.esp32r0_delay:
delay += 0.5
cfg_custom_reset_sequence = cfg.get("custom_reset_sequence")
if cfg_custom_reset_sequence is not None:
CustomReset(self.serial, cfg_custom_reset_sequence)()
elif os.name != "nt":
UnixTightReset(self.serial, delay)()
else:
ClassicReset(self.serial, delay)()
class Redirector(object):
def __init__(self, serial_instance, socket, debug=False, esp32r0delay=False):
self.serial = serial_instance
self.socket = socket
self._write_lock = threading.Lock()
self.rfc2217 = EspPortManager(
self.serial,
self,
esp32r0delay,
logger=logging.getLogger("rfc2217.server") if debug else None,
)
self.log = logging.getLogger("redirector")
def statusline_poller(self):
self.log.debug("status line poll thread started")
while self.alive:
time.sleep(1)
self.rfc2217.check_modem_lines()
self.log.debug("status line poll thread terminated")
def shortcircuit(self):
"""connect the serial port to the TCP port by copying everything
from one side to the other"""
self.alive = True
self.thread_read = threading.Thread(target=self.reader)
self.thread_read.daemon = True
self.thread_read.name = "serial->socket"
self.thread_read.start()
self.thread_poll = threading.Thread(target=self.statusline_poller)
self.thread_poll.daemon = True
self.thread_poll.name = "status line poll"
self.thread_poll.start()
self.writer()
def reader(self):
"""loop forever and copy serial->socket"""
self.log.debug("reader thread started")
while self.alive:
try:
data = self.serial.read(self.serial.in_waiting or 1)
if data:
# escape outgoing data when needed (Telnet IAC (0xff) character)
self.write(b"".join(self.rfc2217.escape(data)))
except socket.error as msg:
self.log.error("{}".format(msg))
# probably got disconnected
break
self.alive = False
self.log.debug("reader thread terminated")
def write(self, data):
"""thread safe socket write with no data escaping. used to send telnet stuff"""
with self._write_lock:
self.socket.sendall(data)
def writer(self):
"""loop forever and copy socket->serial"""
while self.alive:
try:
data = self.socket.recv(1024)
if not data:
break
self.serial.write(b"".join(self.rfc2217.filter(data)))
except socket.error as msg:
self.log.error("{}".format(msg))
# probably got disconnected
break
self.stop()
def stop(self):
"""Stop copying"""
self.log.debug("stopping")
if self.alive:
self.alive = False
self.thread_read.join()
self.thread_poll.join()
def main():
import argparse
parser = argparse.ArgumentParser(
description="RFC 2217 Serial to Network (TCP/IP) redirector.",
epilog="NOTE: no security measures are implemented. "
"Anyone can remotely connect to this service over the network.\n"
"Only one connection at once is supported. "
"When the connection is terminated it waits for the next connect.",
)
parser.add_argument("SERIALPORT")
parser.add_argument(
"-p",
"--localport",
type=int,
help="local TCP port, default: %(default)s",
metavar="TCPPORT",
default=2217,
)
parser.add_argument(
"-v",
"--verbose",
dest="verbosity",
action="count",
help="print more diagnostic messages (option can be given multiple times)",
default=0,
)
parser.add_argument(
"--r0",
help="Use delays necessary for ESP32 revision 0 chips",
action="store_true",
)
args = parser.parse_args()
if args.verbosity > 3:
args.verbosity = 3
level = (logging.WARNING, logging.INFO, logging.DEBUG, logging.NOTSET)[
args.verbosity
]
logging.basicConfig(level=logging.INFO)
# logging.getLogger('root').setLevel(logging.INFO)
logging.getLogger("rfc2217").setLevel(level)
# connect to serial port
ser = serial.serial_for_url(args.SERIALPORT, do_not_open=True)
ser.timeout = 3 # required so that the reader thread can exit
# reset control line as no _remote_ "terminal" has been connected yet
ser.dtr = False
ser.rts = False
logging.info("RFC 2217 TCP/IP to Serial redirector - type Ctrl-C / BREAK to quit")
try:
ser.open()
except serial.SerialException as e:
logging.error("Could not open serial port {}: {}".format(ser.name, e))
sys.exit(1)
logging.info("Serving serial port: {}".format(ser.name))
settings = ser.get_settings()
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("", args.localport))
srv.listen(1)
logging.info("TCP/IP port: {}".format(args.localport))
while True:
try:
client_socket, addr = srv.accept()
logging.info("Connected by {}:{}".format(addr[0], addr[1]))
client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
ser.rts = True
ser.dtr = True
# enter network <-> serial loop
r = Redirector(ser, client_socket, args.verbosity > 0, args.r0)
try:
r.shortcircuit()
finally:
logging.info("Disconnected")
r.stop()
client_socket.close()
ser.dtr = False
ser.rts = False
# Restore port settings (may have been changed by RFC 2217
# capable client)
ser.apply_settings(settings)
except KeyboardInterrupt:
sys.stdout.write("\n")
break
except socket.error as msg:
logging.error(str(msg))
logging.info("--- exit ---")
if __name__ == "__main__":
main()

37
code/.venv/bin/espefuse.py Executable file
View File

@@ -0,0 +1,37 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
#
# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# This executable script is a thin wrapper around the main functionality
# in the espefuse Python package
# When updating this script, please also update esptool.py and espsecure.py
import contextlib
import os
import sys
if os.name != "nt":
# Linux/macOS: remove current script directory to avoid importing this file
# as a module; we want to import the installed espefuse module instead
with contextlib.suppress(ValueError):
executable_dir = os.path.dirname(sys.executable)
sys.path = [
path
for path in sys.path
if not path.endswith(("/bin", "/sbin")) and path != executable_dir
]
# Linux/macOS: delete imported module entry to force Python to load
# the module from scratch; this enables importing espefuse module in
# other Python scripts
with contextlib.suppress(KeyError):
del sys.modules["espefuse"]
import espefuse
if __name__ == "__main__":
espefuse._main()

37
code/.venv/bin/espsecure.py Executable file
View File

@@ -0,0 +1,37 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
#
# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# This executable script is a thin wrapper around the main functionality
# in the espsecure Python package
# When updating this script, please also update esptool.py and espefuse.py
import contextlib
import os
import sys
if os.name != "nt":
# Linux/macOS: remove current script directory to avoid importing this file
# as a module; we want to import the installed espsecure module instead
with contextlib.suppress(ValueError):
executable_dir = os.path.dirname(sys.executable)
sys.path = [
path
for path in sys.path
if not path.endswith(("/bin", "/sbin")) and path != executable_dir
]
# Linux/macOS: delete imported module entry to force Python to load
# the module from scratch; this enables importing espsecure module in
# other Python scripts
with contextlib.suppress(KeyError):
del sys.modules["espsecure"]
import espsecure
if __name__ == "__main__":
espsecure._main()

37
code/.venv/bin/esptool.py Executable file
View File

@@ -0,0 +1,37 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
#
# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# This executable script is a thin wrapper around the main functionality
# in the esptool Python package
# When updating this script, please also update espefuse.py and espsecure.py
import contextlib
import os
import sys
if os.name != "nt":
# Linux/macOS: remove current script directory to avoid importing this file
# as a module; we want to import the installed esptool module instead
with contextlib.suppress(ValueError):
executable_dir = os.path.dirname(sys.executable)
sys.path = [
path
for path in sys.path
if not path.endswith(("/bin", "/sbin")) and path != executable_dir
]
# Linux/macOS: delete imported module entry to force Python to load
# the module from scratch; this enables importing esptool module in
# other Python scripts
with contextlib.suppress(KeyError):
del sys.modules["esptool"]
import esptool
if __name__ == "__main__":
esptool._main()

132
code/.venv/bin/hex2bin.py Executable file
View File

@@ -0,0 +1,132 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# Copyright (c) 2005-2018 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''Intel HEX file format hex2bin convertor utility.'''
VERSION = '2.3.0'
if __name__ == '__main__':
import getopt
import os
import sys
usage = '''Hex2Bin convertor utility.
Usage:
python hex2bin.py [options] INFILE [OUTFILE]
Arguments:
INFILE name of hex file for processing.
OUTFILE name of output file. If omitted then output
will be writing to stdout.
Options:
-h, --help this help message.
-v, --version version info.
-p, --pad=FF pad byte for empty spaces (ascii hex value).
-r, --range=START:END specify address range for writing output
(ascii hex value).
Range can be in form 'START:' or ':END'.
-l, --length=NNNN,
-s, --size=NNNN size of output (decimal value).
'''
pad = None
start = None
end = None
size = None
try:
opts, args = getopt.getopt(sys.argv[1:], "hvp:r:l:s:",
["help", "version", "pad=", "range=",
"length=", "size="])
for o, a in opts:
if o in ("-h", "--help"):
print(usage)
sys.exit(0)
elif o in ("-v", "--version"):
print(VERSION)
sys.exit(0)
elif o in ("-p", "--pad"):
try:
pad = int(a, 16) & 0x0FF
except:
raise getopt.GetoptError('Bad pad value')
elif o in ("-r", "--range"):
try:
l = a.split(":")
if l[0] != '':
start = int(l[0], 16)
if l[1] != '':
end = int(l[1], 16)
except:
raise getopt.GetoptError('Bad range value(s)')
elif o in ("-l", "--lenght", "-s", "--size"):
try:
size = int(a, 10)
except:
raise getopt.GetoptError('Bad size value')
if start != None and end != None and size != None:
raise getopt.GetoptError('Cannot specify START:END and SIZE simultaneously')
if not args:
raise getopt.GetoptError('Hex file is not specified')
if len(args) > 2:
raise getopt.GetoptError('Too many arguments')
except getopt.GetoptError:
msg = sys.exc_info()[1] # current exception
txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool
print(txt)
print(usage)
sys.exit(2)
fin = args[0]
if not os.path.isfile(fin):
txt = "ERROR: File not found: %s" % fin # that's required to get not-so-dumb result from 2to3 tool
print(txt)
sys.exit(1)
if len(args) == 2:
fout = args[1]
else:
# write to stdout
from intelhex import compat
fout = compat.get_binary_stdout()
from intelhex import hex2bin
sys.exit(hex2bin(fin, fout, start, end, size, pad))

135
code/.venv/bin/hex2dump.py Executable file
View File

@@ -0,0 +1,135 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# Copyright (c) 2008-2018 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Show content of hex file as hexdump."""
VERSION = '2.3.0'
USAGE = '''hex2dump: show content of hex file as hexdump.
Usage:
python hex2dump.py [options] HEXFILE
Options:
-h, --help this help message.
-v, --version version info.
-r, --range=START:END specify address range for dumping
(ascii hex value).
Range can be in form 'START:' or ':END'.
--width=N dump N data bytes per line (default: 16).
Arguments:
HEXFILE name of hex file for processing (use '-' to read
from stdin)
'''
import sys
DEFAULT_WIDTH = 16
def hex2dump(hexfile, start=None, end=None, width=DEFAULT_WIDTH):
import intelhex
if hexfile == '-':
hexfile = sys.stdin
try:
ih = intelhex.IntelHex(hexfile)
except (IOError, intelhex.IntelHexError):
e = sys.exc_info()[1] # current exception
sys.stderr.write('Error reading file: %s\n' % e)
return 1
if not (start is None and end is None):
ih = ih[slice(start,end)]
ih.dump(tofile=sys.stdout, width=width)
return 0
def main(argv=None):
import getopt
if argv is None:
argv = sys.argv[1:]
start = None
end = None
width = DEFAULT_WIDTH
try:
opts, args = getopt.getopt(sys.argv[1:], "hvp:r:",
["help", "version", "range=", "width="])
for o, a in opts:
if o in ("-h", "--help"):
print(USAGE)
return 0
elif o in ("-v", "--version"):
print(VERSION)
return 0
elif o in ("-r", "--range"):
try:
l = a.split(":")
if l[0] != '':
start = int(l[0], 16)
if l[1] != '':
end = int(l[1], 16)
except:
raise getopt.GetoptError('Bad range value(s)')
elif o == "--width":
try:
width = int(a)
if width < 1:
raise ValueError
except:
raise getopt.GetoptError('Bad width value (%s)' % a)
if not args:
raise getopt.GetoptError('Hex file is not specified')
if len(args) > 1:
raise getopt.GetoptError('Too many arguments')
except getopt.GetoptError:
msg = sys.exc_info()[1] # current exception
txt = 'ERROR: '+str(msg) # that's required to get not-so-dumb result from 2to3 tool
print(txt)
print(USAGE)
return 2
try:
return hex2dump(args[0], start, end, width)
except IOError:
e = sys.exc_info()[1] # current exception
import errno
if e.errno not in (0, errno.EPIPE):
raise
if __name__ == '__main__':
import sys
sys.exit(main())

90
code/.venv/bin/hexdiff.py Executable file
View File

@@ -0,0 +1,90 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# Copyright (c) 2011-2018 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Produce diff for 2 hex files using hex dump as string representation
of compared data.
"""
VERSION = '2.3.0'
USAGE = '''hexdiff: diff dumps of 2 hex files.
Usage:
python hexdiff.py [options] FILE1 FILE2
Options:
-h, --help this help message.
-v, --version version info.
'''
import sys
def main(argv=None):
import getopt
if argv is None:
argv = sys.argv[1:]
try:
opts, args = getopt.gnu_getopt(argv, 'hv', ['help', 'version'])
for o,a in opts:
if o in ('-h', '--help'):
print(USAGE)
return 0
elif o in ('-v', '--version'):
print(VERSION)
return 0
except getopt.GetoptError:
e = sys.exc_info()[1] # current exception
sys.stderr.write(str(e)+"\n")
sys.stderr.write(USAGE+"\n")
return 1
if len(args) != 2:
sys.stderr.write("ERROR: You should specify 2 files to diff.\n")
sys.stderr.write(USAGE+"\n")
return 1
fname1, fname2 = args
from intelhex import IntelHex, diff_dumps
ih1 = IntelHex(fname1)
ih2 = IntelHex(fname2)
diff_dumps(ih1, ih2, name1=fname1, name2=fname2)
if __name__ == '__main__':
sys.exit(main())

108
code/.venv/bin/hexinfo.py Executable file
View File

@@ -0,0 +1,108 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# Copyright (c) 2015 Andrew Fernandes <andrew@fernandes.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Summarize the information in a hex file by printing the execution
start address (if any), and the address ranges covered by the
data (if any), in YAML format.
"""
VERSION = '2.3.0'
USAGE = '''hexinfo: summarize a hex file's contents.
Usage:
python hexinfo.py [options] FILE [ FILE ... ]
Options:
-h, --help this help message.
-v, --version version info.
'''
import sys
INDENT = ' '
INLIST = '- '
def summarize_yaml(fname):
print("{:s}file: '{:s}'".format(INLIST, fname))
from intelhex import IntelHex
ih = IntelHex(fname)
if ih.start_addr:
keys = sorted(ih.start_addr.keys())
if keys == ['CS','IP']:
entry = ih.start_addr['CS'] * 65536 + ih.start_addr['IP']
elif keys == ['EIP']:
entry = ih.start_addr['EIP']
else:
raise RuntimeError("unknown 'IntelHex.start_addr' found")
print("{:s}entry: 0x{:08X}".format(INDENT, entry))
segments = ih.segments()
if segments:
print("{:s}data:".format(INDENT))
for s in segments:
print("{:s}{:s}{{ first: 0x{:08X}, last: 0x{:08X}, length: 0x{:08X} }}".format(INDENT, INLIST, s[0], s[1]-1, s[1]-s[0]))
print("")
def main(argv=None):
import getopt
if argv is None:
argv = sys.argv[1:]
try:
opts, args = getopt.gnu_getopt(argv, 'hv', ['help', 'version'])
for o,a in opts:
if o in ('-h', '--help'):
print(USAGE)
return 0
elif o in ('-v', '--version'):
print(VERSION)
return 0
except getopt.GetoptError:
e = sys.exc_info()[1] # current exception
sys.stderr.write(str(e)+"\n")
sys.stderr.write(USAGE+"\n")
return 1
if len(args) < 1:
sys.stderr.write("ERROR: You should specify one or more files to summarize.\n")
sys.stderr.write(USAGE+"\n")
return 1
for fname in args:
summarize_yaml(fname)
if __name__ == '__main__':
sys.exit(main())

178
code/.venv/bin/hexmerge.py Executable file
View File

@@ -0,0 +1,178 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# Copyright (c) 2008-2018 Alexander Belchenko
# All rights reserved.
#
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
#
# * Redistributions of source code must retain
# the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce
# the above copyright notice, this list of conditions
# and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the author nor the names
# of its contributors may be used to endorse
# or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Merge content of several hex files into one file."""
VERSION = '2.3.0'
USAGE = '''hexmerge: merge content of hex files.
Usage:
python hexmerge.py [options] FILES...
Options:
-h, --help this help message.
-v, --version version info.
-o, --output=FILENAME output file name (emit output to stdout
if option is not specified)
-r, --range=START:END specify address range for output
(ascii hex value). Both values are inclusive.
Range can be in form 'START:' or ':END'.
--no-start-addr Don't write start addr to output file.
--overlap=METHOD What to do when data in files overlapped.
Supported variants:
* error -- stop and show error message (default)
* ignore -- keep data from first file that
contains data at overlapped address
* replace -- use data from last file that
contains data at overlapped address
Arguments:
FILES list of hex files for merging
(use '-' to read content from stdin)
You can specify address range for each file in the form:
filename:START:END
See description of range option above.
You can omit START or END, so supported variants are:
filename:START: read filename and use data starting from START addr
filename::END read filename and use data till END addr
Use entire file content:
filename
or
filename::
'''
import sys
def main(args=None):
import getopt
output = None
start = None
end = None
write_start_addr = True
overlap = 'error'
if args is None:
args = sys.argv[1:]
try:
opts, args = getopt.gnu_getopt(args, 'hvo:r:',
['help', 'version',
'output=', 'range=',
'no-start-addr', 'overlap=',
])
for o,a in opts:
if o in ('-h', '--help'):
print(USAGE)
return 0
elif o in ('-v', '--version'):
print(VERSION)
return 0
elif o in ('-o', '--output'):
output = a
elif o in ("-r", "--range"):
try:
l = a.split(":")
if l[0] != '':
start = int(l[0], 16)
if l[1] != '':
end = int(l[1], 16)
except (ValueError, IndexError):
raise getopt.GetoptError('Bad range value(s)')
elif o == '--no-start-addr':
write_start_addr = False
elif o == '--overlap':
if a in ('error', 'ignore', 'replace'):
overlap = a
else:
raise getopt.GetoptError('Bad overlap value')
if len(args) == 0:
raise getopt.GetoptError('You should specify file list')
except getopt.GetoptError:
e = sys.exc_info()[1] # current exception
sys.stderr.write(str(e)+"\n")
sys.stderr.write(USAGE+"\n")
return 1
import intelhex
# TODO: move actual merge code into intelhex package as helper function
# and write couple of tests for it.
res = intelhex.IntelHex()
def end_addr_inclusive(addr):
if addr is not None:
return addr + 1
return addr
for f in args:
try:
fname, fstart, fend = intelhex._get_file_and_addr_range(f)
except intelhex._BadFileNotation:
sys.stderr.write('Bad argument: "%s"\n' % f)
sys.stderr.write(USAGE+"\n")
return 1
if fname == '-':
fname = sys.stdin
ih = intelhex.IntelHex(fname)
if (fstart, fend) != (None, None):
ih = ih[fstart:end_addr_inclusive(fend)]
try:
res.merge(ih, overlap)
except intelhex.AddressOverlapError:
e = sys.exc_info()[1] # current exception
sys.stderr.write('Merging: '+fname+"\n")
sys.stderr.write(str(e)+"\n")
return 1
if (start, end) != (None, None):
res = res[start:end_addr_inclusive(end)]
if output is None:
output = sys.stdout
res.write_hex_file(output, write_start_addr)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from utilities.list_serial_ports import lsp
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(lsp())

8
code/.venv/bin/pip Executable file
View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
code/.venv/bin/pip-3.12 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
code/.venv/bin/pip3 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
code/.venv/bin/pip3.12 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from serial.tools.miniterm import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
code/.venv/bin/pyserial-ports Executable file
View File

@@ -0,0 +1,8 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from serial.tools.list_ports import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
code/.venv/bin/python Symbolic link
View File

@@ -0,0 +1 @@
/usr/bin/python3.12

1
code/.venv/bin/python3 Symbolic link
View File

@@ -0,0 +1 @@
python

1
code/.venv/bin/python3.12 Symbolic link
View File

@@ -0,0 +1 @@
python

162
code/.venv/bin/webreplcmd Executable file
View File

@@ -0,0 +1,162 @@
#!/home/rhetenor/Projects/esp/python/.venv/bin/python
import argparse
import os
import sys
import webrepl
examples="""webreplcmd --host 192.168.4.1 --password ulx3s ls
webreplcmd --host 192.168.4.1 --password ulx3s get src-remote-file.txt dest-local-file.txt
webreplcmd --host 192.168.4.1 --password ulx3s put src-local-file.txt dest-remote-file.txt
webreplcmd --host 192.168.4.1 --password ulx3s cat main.py
webreplcmd --host 192.168.4.1 --password ulx3s cmd 'import os; os.listdir()'
"""
parser = argparse.ArgumentParser(description='webrepl - connect to websocket webrepl',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=examples)
parser.add_argument('--host', '-i', default=os.environ.get('WEBREPL_HOST', None), help="Host to connect to")
parser.add_argument('--port', '-P', type=int, default=os.environ.get('WEBREPL_PORT', 8266), help="Port to connect to")
parser.add_argument('--verbose', '-v', action='store_true', help="Verbose information")
parser.add_argument('--debug', '-d', action='store_true', help="Enable debugging messages")
parser.add_argument('--password', '-p', default=os.environ.get('WEBREPL_PASSWORD', None), help="Use following password to connect")
parser.add_argument('--before', '-B', action='append', default=os.environ.get('WEBREPL_BEFORE', None), help="command to execute before")
parser.add_argument('--cmd', '-c', action='append', default=os.environ.get('WEBREPL_CMD', None), help="command to execute")
parser.add_argument('--after', '-A', action='append', default=os.environ.get('WEBREPL_AFTER', None), help="command to execute after")
parser.add_argument('commands', metavar='CMD', type=str, nargs='+',
help='commands for repl')
args = parser.parse_args()
if not args.host:
print("You need to specify host")
parser.print_usage()
sys.exit()
password=''
if not args.password:
print("You need to specify password")
try:
import getpass
password = getpass.getpass()
except:
parser.print_usage()
sys.exit()
else:
password = args.password
if not args.commands or len(args.commands)<1:
print("Command is not recognized/given")
parser.print_usage()
sys.exit()
repl=webrepl.Webrepl(**{})
if args.debug:
repl.debug = True
if args.verbose:
repl.verbose = True
try:
repl.connect(args.host, args.port)
repl.login(password)
except Exception as e:
print("Error connecting to host",args.host,"at port",args.port,":",e)
sys.exit()
if not repl.connected:
print("Not connected. Check your password!")
sys.exit()
if args.before:
for cmd in args.before:
print("[i] Issuing command: "+cmd)
try:
r=repl.send_cmd(cmd)
print(r.decode())
except Exception as e:
print("[e] Error running command:",cmd,":",e)
cmd = args.commands[0].lower()
if cmd == "ver" or cmd == "version":
if args.verbose:
print("[i] Getting version")
ver=repl.get_ver()
print("[i] Version ",ver[0], ver[1], ver[2])
elif cmd == "list" or cmd == "ls":
print("[i] Listing")
r=repl.sendcmd("import os; os.listdir()")
print(r.decode())
elif cmd == "get" or cmd == "download":
if len(args.commands)<3:
sys.stderr.write("Not enough arguments for "+cmd+"\n")
sys.exit()
source=args.commands[1]
dest=args.commands[2]
if args.verbose:
print("[i] Downloading "+source+" to "+dest)
repl.get_file(source, dest)
elif cmd == "put" or cmd == "upload":
if len(args.commands)<3:
sys.stderr.write("Not enough arguments for "+cmd+"\n")
sys.exit()
source=args.commands[1]
dest=args.commands[2]
if args.verbose:
print("[i] Uploading "+source+" to "+dest)
repl.put_file(source, dest)
elif cmd == "del" or cmd == "rm" or cmd == "dele":
if len(args.commands)<2:
sys.stderr.write("Not enough arguments for "+cmd+"\n")
sys.exit()
filename=args.commands[1]
if args.verbose:
print("[i] Deleting "+filename)
r=repl.sendcmd("import os; os.remove('"+filename+"')")
print(r.decode())
elif cmd == "print" or cmd == "cat" or cmd == "type":
if len(args.commands)<2:
sys.stderr.write("Not enough arguments for "+cmd+"\n")
sys.exit()
source=args.commands[1]
if args.verbose:
print("[i] Content of file",source)
r=repl.get_file_content(source)
print(r.decode())
elif cmd == "command" or cmd == "cmd":
if len(args.commands)<2:
sys.stderr.write("Not enough arguments for "+cmd+"\n")
sys.exit()
cmd=args.commands[1]
if args.verbose:
print("[i] Executing "+cmd)
r=repl.sendcmd(cmd)
print(r.decode())
else:
sys.stderr.write("Command not recognized\n")
if args.cmd:
for cmd in args.cmd:
print("[i] Issuing command: "+cmd)
try:
r=repl.send_cmd(cmd)
print(r.decode())
except Exception as e:
print("[e] Error running command:",cmd,":",e)
if args.after:
for cmd in args.after:
print("[i] Issuing command: "+cmd)
try:
r=repl.send_cmd(cmd)
print(r.decode())
except Exception as e:
print("[e] Error running command:",cmd,":",e)
if args.verbose:
print("[i] closing REPL/WS")
repl.disconnect()