feat: 工具链就绪(bleak/pillow/pytest/capstone/androguard) + Web协议提取报告
This commit is contained in:
1 parent
30571dc0a5
commit
cb7eee312f
11 files changed
+8006
No files matched your search
@@ -0,0 +1,323 @@
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const textInput = document.getElementById('textInput');
|
||||
const fontFamily = document.getElementById('fontFamily');
|
||||
const invertColors = document.getElementById('invertColors');
|
||||
const showGrid = document.getElementById('showGrid');
|
||||
const generateBtn = document.getElementById('generateBtn');
|
||||
const upload_rili_text = document.getElementById('upload_rili_text');
|
||||
|
||||
const previewCanvas = document.getElementById('previewCanvas');
|
||||
const codeOutput = document.getElementById('codeOutput');
|
||||
const copyBtn = document.getElementById('copyBtn');
|
||||
const gridInfoText = document.getElementById('gridInfoText');
|
||||
const fontSizeSlider = document.getElementById('fontSizeSlider');
|
||||
const fontSizeValue = document.getElementById('fontSizeValue');
|
||||
const gridSizeSelect = document.getElementById('gridSizeSelect');
|
||||
const currentGridSize = document.getElementById('currentGridSize');
|
||||
const sizeHint = document.getElementById('sizeHint');
|
||||
const ctx = previewCanvas.getContext('2d');
|
||||
document.getElementById('fullAutoActivateBtn').addEventListener('click', fullAutoActivate);
|
||||
|
||||
const previewScale = 8;
|
||||
let fontSizeRatio = 0.85;
|
||||
|
||||
const grid_Size=16;
|
||||
updateGridSize();
|
||||
drawPreview();
|
||||
generateBtn.addEventListener('click', function () {
|
||||
drawPreview();
|
||||
generateCode();
|
||||
});
|
||||
upload_rili_text.addEventListener('click', function () {
|
||||
drawPreview();
|
||||
upload_rili();
|
||||
});
|
||||
copyBtn.addEventListener('click', function () {
|
||||
sendcode();
|
||||
});
|
||||
fontSizeSlider.addEventListener('input', function () {
|
||||
const value = this.value;
|
||||
fontSizeValue.textContent = `${value}%`;
|
||||
fontSizeRatio = value / 100;
|
||||
drawPreview();
|
||||
});
|
||||
gridSizeSelect.addEventListener('change', function () {
|
||||
updateGridSize();
|
||||
drawPreview();
|
||||
});
|
||||
function getCurrentGridSize() {
|
||||
return parseInt(gridSizeSelect.value);
|
||||
}
|
||||
function updateGridSize() {
|
||||
const gridSize = getCurrentGridSize();
|
||||
currentGridSize.textContent = ``;
|
||||
}
|
||||
function formatDate(date) {
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
return `${year}年${month}月${day}日`;
|
||||
}
|
||||
|
||||
function drawPreview() {
|
||||
const text = textInput.value || 'ABCDEFGH';
|
||||
const charCount = text.length;
|
||||
const font = fontFamily.value;
|
||||
const invert = invertColors.checked;
|
||||
const grid = showGrid.checked;
|
||||
const gridSize = getCurrentGridSize();
|
||||
const gridSize_all=gridSize==16?128:96;
|
||||
// 计算实际显示宽度
|
||||
function getCharWidth(char) {
|
||||
if (/[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]/.test(char)) {
|
||||
return gridSize; // 汉字/中文标点
|
||||
}
|
||||
return gridSize/2; // 英文/数字/英文标点
|
||||
}
|
||||
|
||||
function getTotalWidth(str) {
|
||||
let width = 0;
|
||||
for (let char of str) {
|
||||
width += getCharWidth(char);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
const totalDisplayWidth = getTotalWidth(text);
|
||||
|
||||
|
||||
const actualCharWidth = gridSize * getCharWidth(text[0] || 'A');
|
||||
if (totalDisplayWidth > gridSize_all) {
|
||||
alert(`超出总字符(当前:${totalDisplayWidth},时钟倒计时最大支持16个英文或8个汉字,日历倒计时最大支持8个英文或4个汉字)`);
|
||||
|
||||
return;
|
||||
}
|
||||
previewCanvas.width = totalDisplayWidth * previewScale;
|
||||
previewCanvas.height = gridSize * previewScale;
|
||||
|
||||
ctx.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
|
||||
ctx.fillStyle = invert ? '#000000' : '#ffffff';
|
||||
ctx.fillRect(0, 0, previewCanvas.width, previewCanvas.height);
|
||||
|
||||
|
||||
let currentX = 0;
|
||||
ctx.font = `bold ${gridSize * fontSizeRatio * previewScale}px ${font}`;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillStyle = invert ? '#ffffff' : '#000000';
|
||||
|
||||
for (let i = 0; i < charCount; i++) {
|
||||
const currentChar = text[i];
|
||||
const charDisplayWidth = getCharWidth(currentChar);
|
||||
const charPixelWidth = charDisplayWidth * previewScale;
|
||||
const charX = currentX + charPixelWidth / 2;
|
||||
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(currentChar, charX, previewCanvas.height / 2);
|
||||
|
||||
currentX += charPixelWidth;
|
||||
}
|
||||
if (grid) {
|
||||
ctx.strokeStyle = invert ? '#333333' : '#dddddd';
|
||||
for (let x = 0; x <= charCount * gridSize; x++) {
|
||||
const lineX = x * previewScale;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(lineX, 0);
|
||||
ctx.lineTo(lineX, previewCanvas.height);
|
||||
ctx.lineWidth = x % gridSize === 0 ? 2 : 1;
|
||||
ctx.stroke();
|
||||
}
|
||||
for (let y = 0; y <= gridSize; y++) {
|
||||
const lineY = y * previewScale;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, lineY);
|
||||
ctx.lineTo(previewCanvas.width, lineY);
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
async function sendcode() {
|
||||
triggerRxTxCmd('FA');
|
||||
await delay(1000);
|
||||
triggerRxTxCmd('E2');
|
||||
}
|
||||
|
||||
|
||||
function calculateTextWidth(text) {
|
||||
let totalWidth = 0;
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const char = text[i];
|
||||
|
||||
if (/[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u2e80-\u2eff\u3000-\u303f\u31c0-\u31ef\u2f00-\u2fdf\u2e80-\u2eff\u1100-\u11ff\u3130-\u318f\uac00-\ud7af]/.test(char)) {
|
||||
totalWidth += 2; // 中文字符宽度
|
||||
} else {
|
||||
totalWidth += 1; // 英文字符及数字、标点等宽度
|
||||
}
|
||||
}
|
||||
|
||||
return Math.ceil(totalWidth / 2);
|
||||
}
|
||||
|
||||
|
||||
async function generateCode() {
|
||||
const text = textInput.value || 'ABCDEFGH';
|
||||
const gridSize = getCurrentGridSize();
|
||||
const charCount =calculateTextWidth(text) ;
|
||||
const font = fontFamily.value;
|
||||
const invert = invertColors.checked;
|
||||
|
||||
const totalGridWidth = charCount * gridSize;
|
||||
const totalGridHeight = gridSize;
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
tempCanvas.width = totalGridWidth;
|
||||
tempCanvas.height = totalGridHeight;
|
||||
const tempCtx = tempCanvas.getContext('2d');
|
||||
tempCtx.fillStyle = invert ? '#000000' : '#ffffff';
|
||||
tempCtx.fillRect(0, 0, totalGridWidth, totalGridHeight);
|
||||
tempCtx.font = `bold ${totalGridHeight * fontSizeRatio}px ${font}`;
|
||||
tempCtx.textAlign = 'center';
|
||||
tempCtx.textBaseline = 'middle';
|
||||
tempCtx.fillStyle = invert ? '#ffffff' : '#000000';
|
||||
tempCtx.fillText(text, totalGridWidth / 2, totalGridHeight / 2);
|
||||
const imageData = tempCtx.getImageData(0, 0, totalGridWidth, totalGridHeight);
|
||||
const data = imageData.data;
|
||||
const allBytes = [];
|
||||
for (let y = 0; y < totalGridHeight; y++) {
|
||||
const bytesPerLine = totalGridWidth / 8;
|
||||
const lineBytes = new Array(bytesPerLine).fill(0);
|
||||
for (let x = 0; x < totalGridWidth; x++) {
|
||||
const pixelIndex = (y * totalGridWidth + x) * 4;
|
||||
const brightness = (data[pixelIndex] + data[pixelIndex + 1] + data[pixelIndex + 2]) / 3;
|
||||
const bitValue = invert ? (brightness > 128 ? 0 : 1) : (brightness > 128 ? 1 : 0);
|
||||
const byteIndex = Math.floor(x / 8);
|
||||
const bitPosition = 7 - (x % 8);
|
||||
lineBytes[byteIndex] |= (bitValue << bitPosition);
|
||||
}
|
||||
allBytes.push(...lineBytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (gridSize == 16) {
|
||||
if (charCount > 8) {addLog(`设置字符超过了16个(纯中文字符最多4个,纯英文字符最多8个)`); return;}
|
||||
if (charCount > 4) {
|
||||
let code = '0' + 4;
|
||||
for (let i = 0; i < allBytes.length - 1 - (charCount - 4) * 32; i++) {
|
||||
code += `${allBytes[i].toString(16).padStart(2, '0')}`;
|
||||
}
|
||||
triggerRxTxCmd(code);
|
||||
await delay(1000);
|
||||
let code1 = '0' + charCount;
|
||||
for (let i = 128; i < allBytes.length - 1; i++) {
|
||||
code1 += `${allBytes[i].toString(16).padStart(2, '0')}`;
|
||||
}
|
||||
triggerRxTxCmd(code1);
|
||||
} else {
|
||||
let code = '0' + (charCount);
|
||||
for (let i = 0; i < allBytes.length - 1; i++) {
|
||||
code += `${allBytes[i].toString(16).padStart(2, '0')}`;
|
||||
}
|
||||
triggerRxTxCmd(code);
|
||||
}
|
||||
} else if (gridSize == 24) {
|
||||
if (charCount > 4) {addLog(`设置字符超过了8个(纯中文字符最多4个,纯英文字符最多8个)`); return;}
|
||||
|
||||
for (let j = 0; j < charCount; j++) {
|
||||
let code = '990' + j;
|
||||
for (let i = 0; i < 72; i++) {
|
||||
code += `${allBytes[i + j * 72].toString(16).padStart(2, '0')}`;
|
||||
}
|
||||
triggerRxTxCmd(code);
|
||||
await delay(1000);
|
||||
}
|
||||
}
|
||||
const selectedDate = new Date(datePicker.value);
|
||||
let year = selectedDate.getFullYear();
|
||||
let month = selectedDate.getMonth() + 1;
|
||||
let day = selectedDate.getDate();
|
||||
await delay(1000);
|
||||
if (month < 10) month = '0' + month;
|
||||
if (day < 10) day = '0' + day;
|
||||
if (gridSize == 24) {
|
||||
let code2 = 'ffff' + year + month + day;
|
||||
if (year > 2000) {
|
||||
triggerRxTxCmd(code2);
|
||||
};
|
||||
} else {
|
||||
let code2 = 'ff00' + year + month + day;
|
||||
if (year > 2000) {
|
||||
triggerRxTxCmd(code2);
|
||||
};
|
||||
}
|
||||
await delay(1000);
|
||||
triggerRxTxCmd('E2');
|
||||
}
|
||||
|
||||
|
||||
async function upload_rili() {
|
||||
const text = textInput.value || 'ABCDEFGH';
|
||||
const gridSize = getCurrentGridSize();
|
||||
const charCount = calculateTextWidth(text);
|
||||
const font = fontFamily.value;
|
||||
const invert = invertColors.checked;
|
||||
|
||||
const totalGridWidth = charCount * gridSize;
|
||||
const totalGridHeight = gridSize;
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
tempCanvas.width = totalGridWidth;
|
||||
tempCanvas.height = totalGridHeight;
|
||||
const tempCtx = tempCanvas.getContext('2d');
|
||||
tempCtx.fillStyle = invert ? '#000000' : '#ffffff';
|
||||
tempCtx.fillRect(0, 0, totalGridWidth, totalGridHeight);
|
||||
tempCtx.font = `bold ${totalGridHeight * fontSizeRatio}px ${font}`;
|
||||
tempCtx.textAlign = 'center';
|
||||
tempCtx.textBaseline = 'middle';
|
||||
tempCtx.fillStyle = invert ? '#ffffff' : '#000000';
|
||||
tempCtx.fillText(text, totalGridWidth / 2, totalGridHeight / 2);
|
||||
const imageData = tempCtx.getImageData(0, 0, totalGridWidth, totalGridHeight);
|
||||
const data = imageData.data;
|
||||
const allBytes = [];
|
||||
for (let y = 0; y < totalGridHeight; y++) {
|
||||
const bytesPerLine = totalGridWidth / 8;
|
||||
const lineBytes = new Array(bytesPerLine).fill(0);
|
||||
for (let x = 0; x < totalGridWidth; x++) {
|
||||
const pixelIndex = (y * totalGridWidth + x) * 4;
|
||||
const brightness = (data[pixelIndex] + data[pixelIndex + 1] + data[pixelIndex + 2]) / 3;
|
||||
const bitValue = invert ? (brightness > 128 ? 0 : 1) : (brightness > 128 ? 1 : 0);
|
||||
const byteIndex = Math.floor(x / 8);
|
||||
const bitPosition = 7 - (x % 8);
|
||||
lineBytes[byteIndex] |= (bitValue << bitPosition);
|
||||
}
|
||||
allBytes.push(...lineBytes);
|
||||
}
|
||||
if (gridSize == 24) {
|
||||
if (charCount > 4) {addLog(`设置字符超过了8个(纯中文字符最多4个,纯英文字符最多8个)`); return;}
|
||||
|
||||
for (let j = 0; j < charCount; j++) {
|
||||
let code = '990' + j;
|
||||
for (let i = 0; i < 72; i++) {
|
||||
code += `${allBytes[i + j * 72].toString(16).padStart(2, '0')}`;
|
||||
}
|
||||
triggerRxTxCmd(code);
|
||||
await delay(1000);
|
||||
}
|
||||
}
|
||||
triggerRxTxCmd('FA');
|
||||
await delay(1000);
|
||||
triggerRxTxCmd('e10103');
|
||||
await delay(1000);
|
||||
triggerRxTxCmd('E2');
|
||||
}
|
||||
|
||||
|
||||
|
||||
textInput.addEventListener('input', drawPreview);
|
||||
fontFamily.addEventListener('change', drawPreview);
|
||||
invertColors.addEventListener('change', drawPreview);
|
||||
showGrid.addEventListener('change', drawPreview);
|
||||
window.drawPreview = drawPreview;
|
||||
|
||||
});
|
||||
Reference in new issue
Block a user