-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnozzle_offset.html
181 lines (167 loc) · 7.55 KB
/
nozzle_offset.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<H1>Nozzle Offset Calibration Tool</H1>
<style>
body {
background-color: black;
color: red;
margin: 0;
}
:root{
--StreamWidth: 640px;
--StreamWidthHalf: calc(var(--StreamWidth) / 2);
--StreamHeight: 480px;
--StreamHeightHalf: calc(var(--StreamHeight) / 2);
}
#videoContainer {
position: relative;
width: var(--StreamWidth); /* Set the desired video stream width */
height: var(--StreamHeight); /* Set the desired video stream height */
overflow: hidden; /* Prevent crosshair lines from going outside the box */
}
#videoFrame {
width: 100%;
height: 100%;
border: none;
object-fit: cover;
}
.circle-overlay {
position: absolute;
border: 1px solid red;
border-radius: 50%;
pointer-events: none; /* Prevent the overlay from blocking clicks */
width: 70px; /* Initial circle size */
height: 70px; /* Initial circle size */
top: calc(50% - 35px); /* Center vertically */
left: calc(50% - 35px); /* Center horizontally */
}
.crosshair-line {
position: absolute;
background-color: red;
pointer-events: none;
}
#verticalLine {
height: calc(var(--StreamHeight) - 1px);
width: 0px;
top: -2px;
left: var(--StreamWidthHalf);
border: 1px solid red;
transform: translateX(-50%);
z-index: 1;
}
#horizontalLine {
width: var(--StreamWidth);
height: 0px;
top: var(--StreamHeightHalf);
left: -1px;
border: 1px solid red;
z-index: 1;
transform: translateY(-50%);
}
#circleSizeSlider {
width: 400px; /* Adjust the width as needed */
}
</style>
</head>
<body>
<br>
<title>Nozzle Offset Calibration Tool</title>
Input the cam stream info. The default should be accurate assuming you loaded this onto your klipper instance and are using a built in camera.<br>
This is going to be your klipper IP and the stream path: (for example: 192.168.1.50 and /webcam/?action=stream) <br>
You can look in your setting in fluidd or mainsail and find the cam stream path also, and you may have to if you have multiple cameras.<br>
<br>
Camera IP (if not hosted on klipper):<br>
<input type="text" id="camAddress" placeholder="Enter cam address"><br>
Klipper IP:<br>
<input type="text" id="ipAddress" placeholder="Enter IP address"><br>
Stream Path:<br>
<input type="text" id="streampath" value="/webcam/?action=stream"><br>
<button onclick="startVideoStream()">Start Stream</button> <br>
<div id="videoContainer">
<iframe id="videoFrame" frameborder="0"></iframe>
<div class="circle-overlay" id="circleOverlay"></div>
<div class="crosshair-line" id="verticalLine"></div>
<div class="crosshair-line" id="horizontalLine"></div>
</div>
<input type="range" id="circleSizeSlider" min="10" max="100" value="35" step="1" oninput="adjustCircleSize()">
<h2>Current Toolhead Position</h2>
<p>Toolhead Position (mm):</p><p id="positionOutput">Loading position...</p>
<h2>Stored Position</h2>
<p id="storedPosition">No position stored yet</p>
<button onclick="storePosition()">Store Position</button>
<h2>Current Offset</h2>
<p id="offset">No Offset Yet</p>
<script>
let storedX = null;
let storedY = null;
function updateURLs(){
var klipperip = location.host;
var streampath = "/webcam/?action=stream";
var streamurl = "http://" + klipperip + streampath;
const ipInput = document.getElementById('ipAddress');
ipInput.value = klipperip;
}
window.onload = updateURLs;
function startVideoStream() {
const camAddress = document.getElementById('camAddress').value;
const ipAddress = document.getElementById('ipAddress').value;
const camstream = document.getElementById('streampath').value;
const videoFrame = document.getElementById('videoFrame');
if (!camAddress){
videoFrame.setAttribute('src', "http://" + ipAddress + camstream);
}else{
videoFrame.setAttribute('src', "http://" + camAddress + camstream);
}
}
function adjustCircleSize() {
const circleOverlay = document.getElementById('circleOverlay');
const sliderValue = document.getElementById('circleSizeSlider').value;
const radius = parseFloat(sliderValue);
if (!isNaN(radius)) {
circleOverlay.style.width = `${2 * radius}px`;
circleOverlay.style.height = `${2 * radius}px`;
circleOverlay.style.left = `calc(50% - ${radius}px)`;
circleOverlay.style.top = `calc(50% - ${radius}px)`;
}
}
async function getToolheadPosition() {
try {
//const response = await fetch('http://192.168.68.150/printer/objects/query?toolhead=position');
const ipAdd = document.getElementById('ipAddress').value;
const moonurl = "http://" + ipAdd + "/printer/objects/query?toolhead=position";
const response = await fetch(moonurl);
if (response.ok) {
const data = await response.json();
const positionArray = data.result.status.toolhead.position;
const posX = parseFloat(positionArray[0]).toFixed(3);
const posY = parseFloat(positionArray[1]).toFixed(3);
const posZ = parseFloat(positionArray[2]).toFixed(3);
const ext = parseFloat(positionArray[3]).toFixed(3);
const positionOutput = document.getElementById('positionOutput');
positionOutput.textContent = `X: ${posX}, Y: ${posY}`;
if (storedX !== null && storedY !== null) {
const offsetX = (posX - storedX).toFixed(3);
const offsetY = (posY - storedY).toFixed(3);
document.getElementById('offset').textContent = `Offset: X: ${offsetX}, Y: ${offsetY}`;
}
} else {
console.error(`Error fetching data. Status code: ${response.status}`);
}
} catch (error) {
console.error(`An error occurred: ${error.message}`);
}
}
// Fetch position every 1 seconds (adjust as needed)
setInterval(getToolheadPosition, 1000);
function storePosition() {
storedX = parseFloat(document.getElementById('positionOutput').textContent.split(',')[0].split(':')[1].trim());
storedY = parseFloat(document.getElementById('positionOutput').textContent.split(',')[1].split(':')[1].trim());
console.log('Stored X:', storedX, 'Y:', storedY);
storedPosition.textContent = `X: ${storedX} Y: ${storedY}`;
}
</script>
</body>
</html>