This commit is contained in:
backuppc
2025-12-23 13:17:16 +09:00
parent 4d1f131d3e
commit 97e028f3a1
4 changed files with 873 additions and 1018 deletions

View File

@@ -180,9 +180,9 @@ const App: React.FC = () => {
}, [addLog]);
// Tag Transmission Logic
const sendTag = useCallback((tagId: string) => {
const sendTag = useCallback((tagId: string | number) => {
if (agvSerialRef.current) {
const paddedId = tagId.padStart(6, '0').slice(-6);
const paddedId = String(tagId).padStart(6, '0').slice(-6);
const encoder = new TextEncoder();
const cmdBytes = encoder.encode("TAG");
const valBytes = encoder.encode(paddedId);
@@ -704,7 +704,7 @@ const App: React.FC = () => {
return;
}
const id = 1; // Default AGV ID
const id = 0; // Default ACS ID = 0
const len = 1 + 1 + payload.length; // ID + CMD + DATA
const buffer = [0x02, len, id, cmd, ...payload];

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@ interface AcsControlsProps {
const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData }) => {
const [tagId, setTagId] = useState('0001');
const [alias, setAlias] = useState('charger1');
const [targetId, setTargetId] = useState<number>(11); // Default Target ID
const PRESET_ALIASES = [
'charger1', 'charger2',
@@ -21,15 +22,16 @@ const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData
const availableTags = useMemo(() => {
// Extract unique, non-empty RFID tags from map nodes
const tags = mapData.nodes
.filter(n => n.rfidId && n.rfidId.trim() !== '')
.map(n => n.rfidId);
.filter(n => n.rfidId && String(n.rfidId).trim() !== '')
.map(n => String(n.rfidId));
return Array.from(new Set(tags)).sort();
}, [mapData]);
const handleSend = (cmd: number, dataStr?: string, dataByte?: number) => {
if (!isConnected) return;
let payload: number[] = [];
// Payload always starts with Target ID
let payload: number[] = [targetId];
if (dataStr !== undefined) {
// Convert string to ASCII bytes
@@ -50,6 +52,31 @@ const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData
<span className="text-[10px] bg-gray-900 px-1.5 py-0.5 rounded text-gray-500 border border-gray-700">EXT CMD</span>
</h3>
{/* Target ID Selection */}
<div className="flex items-center gap-2 mb-3 bg-gray-900 p-2 rounded border border-gray-700">
<span className="text-xs text-gray-400">Target AGV:</span>
<label className="flex items-center gap-1 cursor-pointer">
<input
type="radio"
name="targetId"
checked={targetId === 11}
onChange={() => setTargetId(11)}
className="text-green-500 focus:ring-0"
/>
<span className={`text-xs ${targetId === 11 ? 'text-green-400 font-bold' : 'text-gray-500'}`}>ID 11</span>
</label>
<label className="flex items-center gap-1 cursor-pointer">
<input
type="radio"
name="targetId"
checked={targetId === 12}
onChange={() => setTargetId(12)}
className="text-green-500 focus:ring-0"
/>
<span className={`text-xs ${targetId === 12 ? 'text-green-400 font-bold' : 'text-gray-500'}`}>ID 12</span>
</label>
</div>
{/* Navigation Commands */}
<div className="space-y-2 mb-4">
{/* Goto Tag */}
@@ -71,7 +98,7 @@ const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData
</datalist>
</div>
<button
onClick={() => handleSend(0x81, tagId)}
onClick={() => handleSend(100, tagId)}
className="bg-gray-700 hover:bg-green-700 text-white text-xs px-3 py-1.5 rounded flex items-center gap-1 transition-colors border border-gray-600"
>
GO <ChevronRight size={10} />
@@ -97,7 +124,7 @@ const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData
</datalist>
</div>
<button
onClick={() => handleSend(0x82, alias)}
onClick={() => handleSend(107, alias)}
className="bg-gray-700 hover:bg-green-700 text-white text-xs px-3 py-1.5 rounded flex items-center gap-1 transition-colors border border-gray-600"
>
GO <ChevronRight size={10} />
@@ -111,26 +138,26 @@ const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData
{/* Action Buttons Grid */}
<div className="grid grid-cols-2 gap-2 mb-3">
<button
onClick={() => handleSend(0x83, undefined, 1)}
onClick={() => handleSend(110, undefined, 1)}
className="flex items-center justify-center gap-2 bg-blue-900/40 hover:bg-blue-800 border border-blue-800 text-blue-200 py-2 rounded text-xs transition-colors"
>
<Package size={14} /> Pick ON
</button>
<button
onClick={() => handleSend(0x83, undefined, 0)}
onClick={() => handleSend(111, undefined, 0)}
className="flex items-center justify-center gap-2 bg-gray-700 hover:bg-gray-600 border border-gray-600 text-gray-300 py-2 rounded text-xs transition-colors"
>
<Package size={14} /> Pick OFF
</button>
<button
onClick={() => handleSend(0x84, undefined, 1)}
onClick={() => handleSend(109, undefined, 1)}
className="flex items-center justify-center gap-2 bg-yellow-900/40 hover:bg-yellow-800 border border-yellow-800 text-yellow-200 py-2 rounded text-xs transition-colors"
>
<Zap size={14} /> Charge ON
</button>
<button
onClick={() => handleSend(0x84, undefined, 0)}
onClick={() => handleSend(109, undefined, 0)}
className="flex items-center justify-center gap-2 bg-gray-700 hover:bg-gray-600 border border-gray-600 text-gray-300 py-2 rounded text-xs transition-colors"
>
<Zap size={14} /> Charge OFF
@@ -141,25 +168,19 @@ const AcsControls: React.FC<AcsControlsProps> = ({ onSend, isConnected, mapData
<div className="mb-3">
<h4 className="text-[10px] text-gray-500 uppercase font-bold mb-1">Lift Control</h4>
<div className="flex gap-1">
<button onClick={() => handleSend(0x85, undefined, 1)} className="flex-1 bg-gray-700 hover:bg-green-700 text-white text-xs py-1.5 rounded border border-gray-600">UP</button>
<button onClick={() => handleSend(0x85, undefined, 0)} className="flex-1 bg-gray-700 hover:bg-red-700 text-white text-xs py-1.5 rounded border border-gray-600">STOP</button>
<button onClick={() => handleSend(0x85, undefined, 2)} className="flex-1 bg-gray-700 hover:bg-green-700 text-white text-xs py-1.5 rounded border border-gray-600">DOWN</button>
<button onClick={() => handleSend(106, undefined, 1)} className="flex-1 bg-gray-700 hover:bg-green-700 text-white text-xs py-1.5 rounded border border-gray-600">UP</button>
<button onClick={() => handleSend(106, undefined, 0)} className="flex-1 bg-gray-700 hover:bg-red-700 text-white text-xs py-1.5 rounded border border-gray-600">STOP</button>
<button onClick={() => handleSend(106, undefined, 2)} className="flex-1 bg-gray-700 hover:bg-green-700 text-white text-xs py-1.5 rounded border border-gray-600">DOWN</button>
</div>
</div>
{/* System Controls (New) */}
<div>
<h4 className="text-[10px] text-gray-500 uppercase font-bold mb-1">System Control</h4>
<div className="grid grid-cols-2 gap-2 mb-2">
<button onClick={() => handleSend(0x86)} className="bg-red-900/40 hover:bg-red-800 text-red-200 border border-red-800 text-xs py-1.5 rounded font-bold">EMG STOP</button>
<button onClick={() => handleSend(0x87)} className="bg-gray-700 hover:bg-gray-600 text-gray-200 border border-gray-600 text-xs py-1.5 rounded">RESET</button>
</div>
<div className="flex items-center justify-between bg-gray-900 p-2 rounded border border-gray-700">
<span className="text-xs text-gray-400">Mark Stop</span>
<div className="flex gap-1">
<button onClick={() => handleSend(0x88, undefined, 1)} className="px-2 py-0.5 text-[10px] bg-green-900 text-green-300 rounded border border-green-800 hover:bg-green-800">ON</button>
<button onClick={() => handleSend(0x88, undefined, 0)} className="px-2 py-0.5 text-[10px] bg-gray-700 text-gray-300 rounded border border-gray-600 hover:bg-gray-600">OFF</button>
</div>
<div className="grid grid-cols-3 gap-2 mb-2">
<button onClick={() => handleSend(101)} className="bg-red-900/40 hover:bg-red-800 text-red-200 border border-red-800 text-xs py-1.5 rounded font-bold">STOP</button>
<button onClick={() => handleSend(102)} className="bg-gray-700 hover:bg-gray-600 text-gray-200 border border-gray-600 text-xs py-1.5 rounded">RESET</button>
<button onClick={() => handleSend(105, undefined, 1)} className="px-2 py-0.5 text-[10px] bg-green-900 text-green-300 rounded border border-green-800 hover:bg-green-800">MARK STOP</button>
</div>
</div>
</div>

View File

@@ -1211,7 +1211,7 @@ const SimulationCanvas: React.FC<SimulationCanvasProps> = ({ activeTool, mapData
return { x: rawX, y: rawY };
};
const handleWheel = (e: React.WheelEvent) => {
const handleWheel = useCallback((e: WheelEvent) => {
e.preventDefault();
const rect = canvasRef.current?.getBoundingClientRect();
if (!rect) return;
@@ -1234,7 +1234,20 @@ const SimulationCanvas: React.FC<SimulationCanvasProps> = ({ activeTool, mapData
const newY = screenY - worldY * newScale;
viewRef.current = { x: newX, y: newY, scale: newScale };
}, []);
// Attach non-passive wheel listener
useEffect(() => {
const canvas = canvasRef.current;
if (canvas) {
canvas.addEventListener('wheel', handleWheel, { passive: false });
}
return () => {
if (canvas) {
canvas.removeEventListener('wheel', handleWheel);
}
};
}, [handleWheel]);
const handleMouseMove = (e: React.MouseEvent) => {
const rect = canvasRef.current?.getBoundingClientRect();
@@ -1547,7 +1560,7 @@ const SimulationCanvas: React.FC<SimulationCanvasProps> = ({ activeTool, mapData
setSelectedItemIds(newSelection);
// Prepare Multi-Drag
const initialStates: Record<string, any> = {};
const initialStates: any = {};
newSelection.forEach(id => {
const n = mapData.nodes.find(o => o.id === id);
if (n) initialStates[id] = { x: n.x, y: n.y };
@@ -1648,7 +1661,6 @@ const SimulationCanvas: React.FC<SimulationCanvasProps> = ({ activeTool, mapData
ref={canvasRef}
width={dimensions.width}
height={dimensions.height}
onWheel={handleWheel}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}