Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dockerfile
image-factory
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM node:latest

WORKDIR /app

COPY . /app

RUN npm install
RUN npm run build
RUN npm install --global serve
RUN ln -s /app/out out/bitaxe-web-flasher

CMD [ "serve", "out" ]
2 changes: 2 additions & 0 deletions image-factory/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.bin
firmware_data.csv
16 changes: 16 additions & 0 deletions image-factory/Dockerfile-expressif
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ARG IDF_VERSION=v5.4
FROM espressif/idf:${IDF_VERSION}

RUN apt-get update && apt-get install -y \
curl \
gnupg \
ca-certificates

RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash -

RUN apt-get install -y nodejs=22.11.0-1nodesource1

RUN npm install -g @angular/cli

ENV IDF_TARGET="esp32s3"

52 changes: 52 additions & 0 deletions image-factory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Build Factory Images With Docker

build-images.sh is a script that builds the factory images with only Docker as a dependency.

After the images are built the script runs the web flasher to allow flashing the Bitaxe
with the newly built dev images. It should open your default browser to http://localhost:3000.

## Requirements

Docker must be installed. https://docs.docker.com/get-started/get-docker/

ESP_MINER_PATH must be set to the path of the ESP-Miner project.

```shell
export ESP_MINER_PATH=~/dev/ESP-Miner
```

It can be set when running the build-images.sh script.

```shell
./image-factory/build-images.sh ESP_MINER_PATH=~/dev/ESP-Miner -t mytag
```

## Building Images

The command is run from the web flasher project root `./image-factory/build-images.sh`. To build images
for all boards specify a tag. The tag defaults to `dev`.

```shell
./image-factory/build-images.sh -t 2.4.2b
```

To build an image for a specific board using expressif/idf version v5.5-dev

```shell
./image-factory/build-images.sh -e v5.5-dev -b 204 -t PR-609
```

If the images were already built previously you can launch the web flasher only with

```shell
./image-factory/build-images.sh -f
```

## Image Location

This build process puts the factory images into the `image-factory` directory. The images
are named `esp-miner-factory-<board>-<tag>.bin`. The web flasher is configured to look for
these local images by loading the `firmware_data.csv` file, supplementing the existing released firmware.

![alt text](image-1.png)

120 changes: 120 additions & 0 deletions image-factory/build-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/bin/bash

if [ ! -d "$ESP_MINER_PATH" ]; then
echo "ESP_MINER_PATH not found: $ESP_MINER_PATH"
exit 1
fi

board=""
idf_version="v5.4"
flash_only=0
tag="dev"

function show_help() {
echo "Usage: build-images.sh [OPTIONS]"
echo "Options:"
echo " -b board: Build only board image. example: 601"
echo " -e: espressif/idf version. default: $idf_version"
echo " -f: Only launch the web flasher"
echo " -t tag: Add tag to image name esp-miner-factory-<board>-<tag>.bin. default: $tag"
}

if [ $# -eq 0 ]; then
show_help
exit 0
fi

while getopts "b:e:ft:" opt; do
case "$opt" in
f)
flash_only=1
;;
b) board=$OPTARG
;;
e) idf_version=$OPTARG
;;
t) tag=$OPTARG
;;
esac
done

if [ $flash_only -eq 0 ]; then
echo "Building esp-miner-factory with idf version $idf_version"
docker build -t esp-miner-factory \
--build-arg IDF_VERSION=$idf_version \
-f image-factory/Dockerfile-expressif .

docker run --rm -v $ESP_MINER_PATH:/project -w /project esp-miner-factory idf.py build
if [ $? -ne 0 ]; then
echo "IDF build failed, check the logs for more information"
exit 1
fi

if [ -z "$board" ]; then
boards="102 201 202 203 204 205 401 402 403 601"
else
boards=$board
fi

for board in $boards; do
if [ -f "$ESP_MINER_PATH/config-$board.cvs" ]; then
# Build config.bin for $board
docker run --rm -w /project -v $ESP_MINER_PATH:/project esp-miner-factory \
/opt/esp/idf/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py \
generate config-${board}.cvs config.bin 0x6000

bin_file="esp-miner-factory-${board}-${tag}.bin"

# Creating image for board $board to public/firmware
docker run --rm -w /project -v $ESP_MINER_PATH:/project \
-v $PWD/image-factory:/firmware \
esp-miner-factory \
/project/merge_bin.sh -c /firmware/$bin_file

# Tell webflasher about our local firmware
name=""
case "$board" in
"102")
name="Max"
;;
"201"|"202"|"203"|"204"|"205")
name="Ultra"
;;
"401"|"402"|"403")
name="Supra"
;;
"601")
name="Gamma"
;;
esac
echo "Found board: $board"
if [ -n "$name" ]; then
echo "$name,$board,$tag,firmware_local/$bin_file" >> image-factory/firmware_data.csv
echo "name: $name"
fi
fi
done
fi

# Remove duplicates from firmware_data.csv
sort -u image-factory/firmware_data.csv -o image-factory/firmware_data.csv

# Build webflasher image
docker build -t bitaxe-web-flasher .

Open web browser to the local webflasher
if command -v xdg-open >/dev/null 2>&1; then
# Linux
xdg-open "http://localhost:3000"
elif command -v open >/dev/null 2>&1; then
# macOS
open "http://localhost:3000"
elif command -v start >/dev/null 2>&1; then
# Windows
start "http://localhost:3000"
fi

# Use start the web flasher with the dev firmware in the build-docker directory
docker run --rm --name bwf \
-v $PWD/image-factory:/app/out/firmware_local \
-p 3000:3000 bitaxe-web-flasher
Binary file added image-factory/image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 31 additions & 1 deletion src/components/LandingHero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import { useTranslation } from 'react-i18next'
import Header from './Header'
import InstructionPanel from './InstructionPanel'
import Selector from './Selector'
import device_data from './firmware_data.json'
import { FirmwareData } from '../lib/types'
import firmware_data from './firmware_data.json'

import { Terminal } from '@xterm/xterm';
import '@xterm/xterm/css/xterm.css';

export default function LandingHero() {
const { t } = useTranslation();
const [device_data, setDeviceData] = useState<FirmwareData>(firmware_data)
const [selectedDevice, setSelectedDevice] = useState<string>('')
const [selectedBoardVersion, setSelectedBoardVersion] = useState('')
const [selectedFirmware, setSelectedFirmware] = useState('')
Expand All @@ -37,6 +39,34 @@ export default function LandingHero() {
const userAgent = navigator.userAgent.toLowerCase();
const isChromium = /chrome|chromium|crios|edge/i.test(userAgent);
setIsChromiumBased(isChromium);

// Released firmware data
const firmwareData = firmware_data

// Append the local built firmware if available
fetch('/firmware_local/firmware_data.csv')
.then((response) => {
if (response.ok) {
response.text().then(data => {
const lines = data.split('\n');
lines.map(line => {
const [device, board, version, path] = line.split(',');

const firmwareDevice = firmwareData.devices.find(d => d.name == device);
if (!firmwareDevice) return;

const firmwareBoard = firmwareDevice.boards.find(b => b.name == board);
if (!firmwareBoard) return;

const existingFirmware = firmwareBoard.supported_firmware.find(f => f.version === version);
if (existingFirmware) return;

firmwareBoard.supported_firmware.push({ version, path });
});
setDeviceData(firmwareData)
})
}
})
}, []);

useEffect(() => {
Expand Down
21 changes: 20 additions & 1 deletion src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
// Add any shared types here
export type DeviceModel = 'max' | 'ultra' | 'supra' | 'gamma' | 'ultrahex' | 'suprahex';
export type DeviceModel = 'max' | 'ultra' | 'supra' | 'gamma' | 'ultrahex' | 'suprahex';

export type FirmwareData = {
devices: Device[]
}

type Device = {
name: string
boards: Board[]
}

type Board = {
name: string
supported_firmware: Firmware[]
}

type Firmware = {
version: string
path: string
}