mirror of
https://github.com/tuya-cloudcutter/tuya-cloudcutter.git
synced 2026-02-19 21:51:18 +01:00
Fix filename returned by choose_firmware to be filename only.
Add validation to firmware file passed in via -f argument. List custom firmware present but ignored because of not meeting naming requirements. Add 3rd party firmware to custom-firmware to be chosen from without a user need to download. Add a README.md to custom-firmware.
This commit is contained in:
@@ -49,12 +49,13 @@ Knowing this, you can run `sudo ./tuya-cloudcutter.sh` without any parameters. T
|
||||
|
||||
|
||||
## Flashing custom firmware
|
||||
* Copy your new firmware .bin file (UG only!) to ./custom-firmware
|
||||
* Copy your new firmware .bin file (UG or UF2 files only!) to ./custom-firmware
|
||||
* Find your device name, as instructed in the steps above.
|
||||
* Run `sudo ./tuya-cloudcutter.sh`. You can specify device profile name and firmware file using `-p` and `-f`, respectively (this is optional). Example: `sudo ./tuya-cloudcutter.sh -p avatar-asl04-tv-backlight -f custom_firmware_UG_file.bin`
|
||||
* Run `sudo ./tuya-cloudcutter.sh`. You can specify device profile name and firmware file using `-p` and `-f`, respectively (this is optional). Example: `sudo ./tuya-cloudcutter.sh -p avatar-asl04-tv-backlight -f custom_firmware_file.bin`
|
||||
* Follow the instructions from the script to turn off/on your device 6 times during 2 steps (similar to the steps above)
|
||||
* If all goes well, your device is now running your custom firmware, enjoy!
|
||||
|
||||
### Custom firmware options
|
||||
|
||||
Please see the [wiki](https://github.com/tuya-cloudcutter/tuya-cloudcutter/wiki/FAQ#what-custom-firmware-options-are-available) for information about available 3rd party firmware.
|
||||
Some common 3rd party firmware files have been included by default. See [custom-firmware](https://github.com/tuya-cloudcutter/tuya-cloudcutter/tree/main/custom-firmware) for further information.
|
||||
For user-supplied custom options, please see the [wiki](https://github.com/tuya-cloudcutter/tuya-cloudcutter/wiki/FAQ#what-custom-firmware-options-are-available) for information about available 3rd party firmware.
|
||||
|
||||
@@ -37,12 +37,14 @@ if [ $METHOD_FLASH ]; then
|
||||
# Select the right firmware
|
||||
if [ "${FIRMWARE}" == "" ]; then
|
||||
run_in_docker pipenv run python3 get_input.py -w /work -o /work/firmware.txt choose-firmware -c "${CHIP}"
|
||||
if [ ! $? -eq 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
FIRMWARE=$(cat firmware.txt)
|
||||
rm -f firmware.txt
|
||||
else
|
||||
run_in_docker pipenv run python3 get_input.py -w /work -o /work/firmware.txt validate-firmware-file "${FIRMWARE}" -c "${CHIP}"
|
||||
fi
|
||||
if [ ! $? -eq 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
FIRMWARE=$(cat firmware.txt)
|
||||
rm -f firmware.txt
|
||||
fi
|
||||
|
||||
echo "Selected Device Slug: ${DEVICESLUG}"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
custom-firmware/OpenBeken-v1.17.130_bk7231n.ug.bin
Normal file
BIN
custom-firmware/OpenBeken-v1.17.130_bk7231n.ug.bin
Normal file
Binary file not shown.
BIN
custom-firmware/OpenBeken-v1.17.130_bk7231t.ug.bin
Normal file
BIN
custom-firmware/OpenBeken-v1.17.130_bk7231t.ug.bin
Normal file
Binary file not shown.
20
custom-firmware/README.md
Normal file
20
custom-firmware/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Custom Firmware
|
||||
This is the directory you may place custom firmware for flashing. The selectable list will be automatically filtered to binaries that match your chosen profile. If you need newer or more custom firmware, you can add them here, abiding by the naming rules below. Custom firmware must be in the format of either Tuya's `UG` bin file for OTA or the `.uf2` file format.
|
||||
|
||||
# Naming rules
|
||||
If you place custom files here, they must include either `bk7231t` or `bk7231n` in the file name which will allow Tuya-CloudCutter to verify you are flashing a firmware that matches the profile you are using.
|
||||
|
||||
# Included 3rd party firmware
|
||||
For convenience, binaries from the two most prevelant options, [ESPHome (Kickstart version by LibreTiny)](https://github.com/libretiny-eu/esphome-kickstart) and [OpenBeken (OpenBK7231T_App)](https://github.com/openshwprojects/OpenBK7231T_App) have been included automatically. All included binaries will flash your device with a firmware that will put the device into AP mode where you must connect and configure the device as appropriate.
|
||||
|
||||
### ESPHome (Kickstart by LibreTiny)
|
||||
The AP provided by this firmware will start with `kickstart-` followed by the chip family name. You can connect with no password and configure your network information. Once connected you can enter the captive portal at IP address 192.168.4.1 where you will be able join the device to your local network. Once joined to your network, you can scan pin functionality and flash a custom updated firmware (with the .uf2 format) with a more customized configuration.
|
||||
|
||||
* See https://github.com/libretiny-eu/esphome-kickstart for guides and support.
|
||||
* See https://github.com/libretiny-eu/esphome-kickstart/releases for the most recent binaries.
|
||||
|
||||
### OpenBekn (OpenBK7231T_App)
|
||||
The AP provided by this firmware will start with `OpenBK` followed by the chip family name and part of the device's MAC address. Once connected you can enter the captive portal at IP address 192.168.4.1 where you will be able to join the device to your local network. Once joined to your network, you can begin configuring your device and use all tools available to OpenBeken.
|
||||
|
||||
* See https://github.com/openshwprojects/OpenBK7231T_App for guides and support.
|
||||
* See https://github.com/openshwprojects/OpenBK7231T_App/releases for the most recent binaries.
|
||||
@@ -12,9 +12,10 @@ import requests
|
||||
|
||||
class FirmwareType(Enum):
|
||||
INVALID = 0
|
||||
IGNORED = 1
|
||||
VALID_UG = 2
|
||||
VALID_UF2 = 3
|
||||
IGNORED_HEADER = 1
|
||||
IGNORED_FILENAME = 2
|
||||
VALID_UG = 3
|
||||
VALID_UF2 = 4
|
||||
|
||||
|
||||
UF2_UG_SUFFIX = "-extracted.ug.bin"
|
||||
@@ -153,8 +154,7 @@ def save_combined_profile(profile_dir, device, profile):
|
||||
json.dump(combined, f, indent="\t")
|
||||
return abspath(combined_path)
|
||||
|
||||
|
||||
def validate_firmware_file(firmware: str, chip: str = None) -> FirmwareType:
|
||||
def validate_firmware_file_internal(firmware: str, chip: str = None) -> FirmwareType:
|
||||
FILE_MAGIC_DICT = {
|
||||
b"RBL\x00": "RBL",
|
||||
b"\x43\x09\xb5\x96": "QIO",
|
||||
@@ -189,14 +189,14 @@ def validate_firmware_file(firmware: str, chip: str = None) -> FirmwareType:
|
||||
if b"bk7231" in rbl_ver:
|
||||
if chip and chip.encode() not in rbl_ver:
|
||||
# wrong chip type
|
||||
return FirmwareType.IGNORED
|
||||
return FirmwareType.IGNORED_HEADER
|
||||
# correct chip type
|
||||
return FirmwareType.VALID_UG
|
||||
# check chip by filename
|
||||
if "bk7231" in base.lower():
|
||||
if chip and chip not in base.lower():
|
||||
# wrong chip type
|
||||
return FirmwareType.IGNORED
|
||||
return FirmwareType.IGNORED_FILENAME
|
||||
# correct chip type
|
||||
return FirmwareType.VALID_UG
|
||||
print(
|
||||
@@ -208,7 +208,7 @@ def validate_firmware_file(firmware: str, chip: str = None) -> FirmwareType:
|
||||
|
||||
if file_type == "UF2":
|
||||
if not chip:
|
||||
return FirmwareType.IGNORED
|
||||
return FirmwareType.IGNORED_HEADER
|
||||
try:
|
||||
from ltchiptool import get_version
|
||||
from uf2tool.models import Block
|
||||
@@ -223,7 +223,7 @@ def validate_firmware_file(firmware: str, chip: str = None) -> FirmwareType:
|
||||
block = Block()
|
||||
block.decode(header)
|
||||
if UF2_FAMILY_MAP[chip] != block.family.id:
|
||||
return FirmwareType.IGNORED
|
||||
return FirmwareType.IGNORED_HEADER
|
||||
return FirmwareType.VALID_UF2
|
||||
|
||||
|
||||
@@ -330,15 +330,18 @@ def choose_firmware(ctx, chip: str = None):
|
||||
firmware_dir = ctx.obj["firmware_dir"]
|
||||
files = listdir(firmware_dir)
|
||||
options = {}
|
||||
invalid_filenames = {}
|
||||
for file in files:
|
||||
if file.startswith("."):
|
||||
if file.startswith(".") or file.endswith(".md"):
|
||||
continue
|
||||
if file.endswith(UF2_UG_SUFFIX):
|
||||
continue
|
||||
path = join(firmware_dir, file)
|
||||
fw_type = validate_firmware_file(path, chip and chip.lower())
|
||||
fw_type = validate_firmware_file_internal(path, chip and chip.lower())
|
||||
if fw_type in [FirmwareType.VALID_UG, FirmwareType.VALID_UF2]:
|
||||
options[file] = fw_type
|
||||
elif fw_type in [FirmwareType.IGNORED_FILENAME]:
|
||||
invalid_filenames[file] = file
|
||||
|
||||
if not options:
|
||||
print(
|
||||
@@ -347,6 +350,12 @@ def choose_firmware(ctx, chip: str = None):
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
|
||||
if invalid_filenames:
|
||||
print("\nThe following files were ignored because they do not meet naming requirements and the chip type could not be determined:")
|
||||
for invalid_filename in invalid_filenames:
|
||||
print(invalid_filename)
|
||||
print("Please see https://github.com/tuya-cloudcutter/tuya-cloudcutter/tree/main/custom-firmware#naming-rules for more information.\n")
|
||||
|
||||
prompt = "Select your custom firmware file"
|
||||
if chip:
|
||||
@@ -390,8 +399,29 @@ def choose_firmware(ctx, chip: str = None):
|
||||
# write RBL data
|
||||
f.write(rbl)
|
||||
|
||||
ctx.obj["output"].write(path)
|
||||
ctx.obj["output"].write(basename(path))
|
||||
|
||||
@cli.command()
|
||||
@click.argument("filename", type=str)
|
||||
@click.option(
|
||||
"-c",
|
||||
"--chip",
|
||||
type=click.Choice(["bk7231t", "bk7231n"], case_sensitive=False),
|
||||
default=None,
|
||||
)
|
||||
@click.pass_context
|
||||
def validate_firmware_file(ctx, filename: str, chip: str = None):
|
||||
chip = chip and chip.upper()
|
||||
firmware_dir = ctx.obj["firmware_dir"]
|
||||
fw_type = validate_firmware_file_internal(join(firmware_dir, filename), chip and chip.lower())
|
||||
if fw_type not in [FirmwareType.VALID_UG, FirmwareType.VALID_UF2]:
|
||||
print(
|
||||
f"The firmware file supplied ({filename}) is not valid for the chosen profile type of {chip}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
exit(1)
|
||||
|
||||
ctx.obj["output"].write(filename)
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli(obj={})
|
||||
|
||||
Reference in New Issue
Block a user