Add oem tool

This commit is contained in:
Sacha Weatherstone 2022-11-02 22:25:45 +10:00
parent 6ccb434b4e
commit 5f997f5bc8
No known key found for this signature in database
GPG key ID: 7AB2D7E206124B31
3 changed files with 331 additions and 0 deletions

View file

@ -21,7 +21,9 @@
"@heroicons/react": "^2.0.12",
"@leenguyen/react-flip-clock-countdown": "^1.3.1",
"@mdx-js/react": "^1.6.22",
"@meshtastic/meshtasticjs": "^0.6.113",
"autoprefixer": "^10.4.13",
"base64-js": "^1.5.1",
"dotenv": "^16.0.3",
"framer-motion": "^6.5.1",
"postcss": "^8.4.18",

View file

@ -11,12 +11,14 @@ specifiers:
'@leenguyen/react-flip-clock-countdown': ^1.3.1
'@mdx-js/react': ^1.6.22
'@meshtastic/eslint-config': ^1.0.8
'@meshtastic/meshtasticjs': ^0.6.113
'@tailwindcss/typography': ^0.5.7
'@tsconfig/docusaurus': ^1.0.6
'@types/node': ^18.11.9
'@types/react': ^18.0.24
'@types/react-dom': ^18.0.8
autoprefixer: ^10.4.13
base64-js: ^1.5.1
dotenv: ^16.0.3
framer-motion: ^6.5.1
postcss: ^8.4.18
@ -40,7 +42,9 @@ dependencies:
'@heroicons/react': 2.0.12_react@17.0.2
'@leenguyen/react-flip-clock-countdown': 1.3.1_react@17.0.2
'@mdx-js/react': 1.6.22_react@17.0.2
'@meshtastic/meshtasticjs': 0.6.113
autoprefixer: 10.4.13_postcss@8.4.18
base64-js: 1.5.1
dotenv: 16.0.3
framer-motion: 6.5.1_sfoxds7t5ydpegc3knd667wn6m
postcss: 8.4.18
@ -2652,6 +2656,18 @@ packages:
- supports-color
dev: true
/@meshtastic/meshtasticjs/0.6.113:
resolution: {integrity: sha512-4/Qlqof/Dm2gWS1nqZ/H/csYy5o7EjdKlGWCBFQjAA5s9PmZ4vMI20UdoSaAz3+DvW7CYCzAx3h1e5WwsClF0A==}
dependencies:
'@protobuf-ts/runtime': 2.8.1
'@serialport/stream': 10.3.0
glob: 8.0.3
serialport: 10.4.0
sub-events: 1.9.0
transitivePeerDependencies:
- supports-color
dev: false
/@motionone/animation/10.13.1:
resolution: {integrity: sha512-dxQ+1wWxL6iFHDy1uv6hhcPjIdOg36eDT56jN4LI7Z5HZRyLpq8x1t7JFQclo/IEIb+6Bk4atmyinGFdXVECuA==}
dependencies:
@ -2721,6 +2737,106 @@ packages:
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
dev: false
/@protobuf-ts/runtime/2.8.1:
resolution: {integrity: sha512-D9M5hSumYCovIfNllt7N6ODh4q+LrjiMWtNETvooaf+a2XheZJ7kgjFlsFghti0CFWwtA//of4JXQfw9hU+cCw==}
dev: false
/@serialport/binding-mock/10.2.2:
resolution: {integrity: sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==}
engines: {node: '>=12.0.0'}
dependencies:
'@serialport/bindings-interface': 1.2.2
debug: 4.3.4
transitivePeerDependencies:
- supports-color
dev: false
/@serialport/bindings-cpp/10.7.0:
resolution: {integrity: sha512-Xx1wA2UCG2loS32hxNvWJI4smCzGKhWqE85//fLRzHoGgE1lSLe3Nk7W40/ebrlGFHWRbQZmeaIF4chb2XLliA==}
engines: {node: '>=12.17.0 <13.0 || >=14.0.0'}
requiresBuild: true
dependencies:
'@serialport/bindings-interface': 1.2.1
'@serialport/parser-readline': 10.3.0
debug: 4.3.4
node-addon-api: 4.3.0
node-gyp-build: 4.5.0
transitivePeerDependencies:
- supports-color
dev: false
/@serialport/bindings-interface/1.2.1:
resolution: {integrity: sha512-63Dyqz2gtryRDDckFusOYqLYhR3Hq/M4sEdbF9i/VsvDb6T+tNVgoAKUZ+FMrXXKnCSu+hYbk+MTc0XQANszxw==}
engines: {node: ^12.22 || ^14.13 || >=16}
dev: false
/@serialport/bindings-interface/1.2.2:
resolution: {integrity: sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==}
engines: {node: ^12.22 || ^14.13 || >=16}
dev: false
/@serialport/parser-byte-length/10.3.0:
resolution: {integrity: sha512-pJ/VoFemzKRRNDHLhFfPThwP40QrGaEnm9TtwL7o2GihEPwzBg3T0bN13ew5TpbbUYZdMpUtpm3CGfl6av9rUQ==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-cctalk/10.3.0:
resolution: {integrity: sha512-8ujmk8EvVbDPrNF4mM33bWvUYJOZ0wXbY3WCRazHRWvyCdL0VO0DQvW81ZqgoTpiDQZm5r8wQu9rmuemahF6vQ==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-delimiter/10.3.0:
resolution: {integrity: sha512-9E4Vj6s0UbbcCCTclwegHGPYjJhdm9qLCS0lowXQDEQC5naZnbsELemMHs93nD9jHPcyx1B4oXkMnVZLxX5TYw==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-inter-byte-timeout/10.3.0:
resolution: {integrity: sha512-wKP0QK85NHgvT6BBB1qBfKBBU4pf8kespNXAZBUYmFT+P4n8r8IZE2mqigCD+AiZcfWNQoAizwOsT/Jx/qeVig==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-packet-length/10.3.0:
resolution: {integrity: sha512-bj0cWzt8YSQj/E5fRQVYdi4TsfTlZQrXlXrUwjyTsCONv8IPOHzsz+yY0fw5SEMiJtaLyqvPkCHLsttOd/zFsg==}
engines: {node: '>=8.6.0'}
dev: false
/@serialport/parser-readline/10.3.0:
resolution: {integrity: sha512-ki3ATZ3/RAqnqGROBKE7k+OeZ0DZXZ53GTca4q71OU5RazbbNhTOBQLKLXD3v9QZXCMJdg4hGW/2Y0DuMUqMQg==}
engines: {node: '>=12.0.0'}
dependencies:
'@serialport/parser-delimiter': 10.3.0
dev: false
/@serialport/parser-ready/10.3.0:
resolution: {integrity: sha512-1owywJ4p592dJyVrEJZPIh6pUZ3/y/LN6kGTDH2wxdewRUITo/sGvDy0er5i2+dJD3yuowiAz0dOHSdz8tevJA==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-regex/10.3.0:
resolution: {integrity: sha512-tIogTs7CvTH+UUFnsvE7i33MSISyTPTGPWlglWYH2/5coipXY503jlaYS1YGe818wWNcSx6YAjMZRdhTWwM39w==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-slip-encoder/10.3.0:
resolution: {integrity: sha512-JI0ILF5sylWn8f0MuMzHFBix/iMUTa79/Z95KaPZYnVaEdA7h7hh/o21Jmon/26P3RJwL1SNJCjZ81zfan+LtQ==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/parser-spacepacket/10.3.0:
resolution: {integrity: sha512-PDF73ClEPsClD1FEJZHNuBevDKsJCkqy/XD5+S5eA6+tY5D4HLrVgSWsg+3qqB6+dlpwf2CzHe+uO8D3teuKHA==}
engines: {node: '>=12.0.0'}
dev: false
/@serialport/stream/10.3.0:
resolution: {integrity: sha512-7sooi5fHogYNVEJwxVdg872xO6TuMgQd2E9iRmv+o8pk/1dbBnPkmH6Ka3st1mVE+0KnIJqVlgei+ncSsqXIGw==}
engines: {node: '>=12.0.0'}
dependencies:
'@serialport/bindings-interface': 1.2.1
debug: 4.3.4
transitivePeerDependencies:
- supports-color
dev: false
/@sideway/address/4.1.4:
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
dependencies:
@ -3703,6 +3819,10 @@ packages:
resolution: {integrity: sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==}
dev: false
/base64-js/1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
dev: false
/batch/0.6.1:
resolution: {integrity: sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=}
dev: false
@ -3780,6 +3900,12 @@ packages:
balanced-match: 1.0.2
concat-map: 0.0.1
/brace-expansion/2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: false
/braces/3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
@ -5505,6 +5631,17 @@ packages:
once: 1.4.0
path-is-absolute: 1.0.1
/glob/8.0.3:
resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==}
engines: {node: '>=12'}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 5.1.0
once: 1.4.0
dev: false
/global-dirs/3.0.0:
resolution: {integrity: sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==}
engines: {node: '>=10'}
@ -6642,6 +6779,13 @@ packages:
dependencies:
brace-expansion: 1.1.11
/minimatch/5.1.0:
resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==}
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: false
/minimist/1.2.6:
resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==}
@ -6691,6 +6835,10 @@ packages:
tslib: 2.4.0
dev: false
/node-addon-api/4.3.0:
resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==}
dev: false
/node-emoji/1.11.0:
resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==}
dependencies:
@ -6714,6 +6862,11 @@ packages:
engines: {node: '>= 6.13.0'}
dev: false
/node-gyp-build/4.5.0:
resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==}
hasBin: true
dev: false
/node-releases/2.0.6:
resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
@ -8337,6 +8490,28 @@ packages:
dependencies:
randombytes: 2.1.0
/serialport/10.4.0:
resolution: {integrity: sha512-PszPM5SnFMgSXom60PkKS2A9nMlNbHkuoyRBlzdSWw9rmgOn258+V0dYbWMrETJMM+TJV32vqBzjg5MmmUMwMw==}
engines: {node: '>=12.0.0'}
dependencies:
'@serialport/binding-mock': 10.2.2
'@serialport/bindings-cpp': 10.7.0
'@serialport/parser-byte-length': 10.3.0
'@serialport/parser-cctalk': 10.3.0
'@serialport/parser-delimiter': 10.3.0
'@serialport/parser-inter-byte-timeout': 10.3.0
'@serialport/parser-packet-length': 10.3.0
'@serialport/parser-readline': 10.3.0
'@serialport/parser-ready': 10.3.0
'@serialport/parser-regex': 10.3.0
'@serialport/parser-slip-encoder': 10.3.0
'@serialport/parser-spacepacket': 10.3.0
'@serialport/stream': 10.3.0
debug: 4.3.4
transitivePeerDependencies:
- supports-color
dev: false
/serve-handler/6.1.3:
resolution: {integrity: sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==}
dependencies:
@ -8682,6 +8857,11 @@ packages:
postcss-selector-parser: 6.0.10
dev: false
/sub-events/1.9.0:
resolution: {integrity: sha512-dnFBayilG9Ku0k/lNs1Y7WV4kv91+ovCoeBV3uIYrY49DylvBb6z9d9ED2ctcrvX2YlReFalpCgJNtSgmrOaJg==}
engines: {node: '>=10.0.0'}
dev: false
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}

149
src/pages/tools/OEM.tsx Normal file
View file

@ -0,0 +1,149 @@
import React, { useEffect, useState } from 'react';
import { fromByteArray, toByteArray } from 'base64-js';
import { Protobuf } from '@meshtastic/meshtasticjs';
import Layout from '@theme/Layout';
const OEM = (): JSX.Element => {
const [oemAesKey, setOemAesKey] = useState<Uint8Array>(new Uint8Array());
const [oemFont, setOemFont] = useState<Protobuf.ScreenFonts>(
Protobuf.ScreenFonts.FONT_MEDIUM,
);
const [oemIconBits, setOemIconBits] = useState<Uint8Array>(new Uint8Array());
const [oemIconHeight, setOemIconHeight] = useState<number>(0);
const [oemIconWidth, setOemIconWidth] = useState<number>(0);
const [oemText, setOemText] = useState<string>('');
const [oemBytes, setOemBytes] = useState<Uint8Array>(new Uint8Array());
const encoder = new TextEncoder();
useEffect(() => {
setOemBytes(
Protobuf.OEMStore.toBinary({
oemAesKey,
oemFont,
oemIconBits,
oemIconHeight,
oemIconWidth,
oemText,
}),
);
}, [oemAesKey, oemFont, oemIconBits, oemIconHeight, oemIconWidth, oemText]);
const enumOptions = Protobuf.ScreenFonts
? Object.entries(Protobuf.ScreenFonts).filter(
(value) => typeof value[1] === 'number',
)
: [];
const readFile = (file: File) => {
return new Promise((resolve: (value: ArrayBuffer) => void, reject) => {
const reader = new FileReader();
reader.onload = (res) => {
resolve(res.target.result as ArrayBuffer);
};
reader.onerror = (err) => reject(err);
reader.readAsArrayBuffer(file);
});
};
return (
<Layout title="OEM Generator" description="OEM Bin Generator">
<div className="container mt-8 flex flex-col gap-3">
<span>AES Key</span>
<div className="flex gap-2">
<button
onClick={() => {
const key = new Uint8Array(128 / 8);
setOemAesKey(crypto.getRandomValues(key));
}}
className="cursor-pointer rounded-md bg-tertiary p-2 hover:brightness-90"
>
Generate 128bit
</button>
<button
onClick={() => {
const key = new Uint8Array(256 / 8);
setOemAesKey(crypto.getRandomValues(key));
}}
className="mr-auto cursor-pointer rounded-md bg-tertiary p-2 hover:brightness-90"
>
Generate 256bit
</button>
</div>
<input
type="text"
name="oemAesKey"
value={fromByteArray(oemAesKey)}
onChange={(e) => {
setOemAesKey(toByteArray(e.target.value));
}}
/>
<span>Font</span>
<select
onChange={(e) => {
setOemFont(parseInt(e.target.value));
}}
>
{enumOptions.map(([name, value], index) => (
<option key={index} value={value}>
{name}
</option>
))}
</select>
<span>Logo XBM</span>
<input
type="file"
name="file"
onChange={(e) => {
readFile(e.target.files[0]).then((data) => {
setOemIconBits(new Uint8Array(data));
});
}}
/>
<span>Logo Height</span>
<input
type="number"
name="oemIconHeight"
onChange={(e) => {
setOemIconHeight(parseInt(e.target.value));
}}
/>
<span>Logo Width</span>
<input
type="number"
name="oemIconWidth"
onChange={(e) => {
setOemIconWidth(parseInt(e.target.value));
}}
/>
<span>Boot Text</span>
<input
type="text"
name="oemText"
onChange={(e) => {
setOemText(e.target.value);
}}
/>
<a
className="cursor-pointer rounded-md bg-tertiary p-2 hover:brightness-90"
download="OEM.bin"
onClick={() => {
const blob = new Blob([oemBytes], {
type: 'application/octet-stream',
});
window.open(URL.createObjectURL(blob));
}}
>
Download
</a>
{oemBytes.toString()}
</div>
</Layout>
);
};
export default OEM;