package de.opcua.app.rest; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import java.io.IOException; public class HelpPageHandler implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { String path = exchange.getRequestURI().getPath(); String query = exchange.getRequestURI().getQuery(); // Determine language from query parameter or Accept-Language header String lang = "en"; // default if (query != null && query.contains("lang=de")) { lang = "de"; } else if (query != null && query.contains("lang=en")) { lang = "en"; } else { String acceptLang = exchange.getRequestHeaders().getFirst("Accept-Language"); if (acceptLang != null && acceptLang.toLowerCase().startsWith("de")) { lang = "de"; } } String html = buildHelpPage(lang); byte[] bytes = html.getBytes("UTF-8"); exchange.getResponseHeaders().set("Content-Type", "text/html; charset=UTF-8"); exchange.sendResponseHeaders(200, bytes.length); exchange.getResponseBody().write(bytes); exchange.getResponseBody().close(); } private String buildHelpPage(String lang) { if ("de".equals(lang)) { return buildGermanHelp(); } else { return buildEnglishHelp(); } } private String buildEnglishHelp() { return "" + "" + "
" + "" + "" + "Complete reference for integrating with the OPC UA HTTP API
" + "The OPC UA HTTP API provides RESTful access to OPC UA server data. All endpoints accept and return JSON.
" + "Base URL: http://localhost:8081
Content-Type: application/json
Currently, no authentication is required for local access. For production deployment, use HTTPS with client certificates.
" + "Get OPC UA connection status
" + "{" +
" \"connected\": true," +
" \"timestamp\": 1707989123456" +
"}" +
"const response = await fetch('/api/status');" +
"const data = await response.json();" +
"console.log('Connected:', data.connected);" +
"Read a value from an OPC UA node
" + "{" +
" \"nodeId\": \"ns=2;s=Temperature\"" +
"}" +
"{" +
" \"success\": true," +
" \"value\": \"25.5\"," +
" \"timestamp\": 1707989123456" +
"}" +
"const response = await fetch('/api/read', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({nodeId: 'ns=2;s=Temperature'})" +
"});" +
"const data = await response.json();" +
"console.log('Temperature:', data.value);" +
"Write a value to an OPC UA node
" + "{" +
" \"nodeId\": \"ns=2;s=SetPoint\"," +
" \"value\": \"30.0\"" +
"}" +
"{" +
" \"success\": true," +
" \"written\": true" +
"}" +
"const response = await fetch('/api/write', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({" +
" nodeId: 'ns=2;s=SetPoint'," +
" value: '30.0'" +
" })" +
"});" +
"const data = await response.json();" +
"console.log('Write successful:', data.written);" +
"Browse OPC UA node hierarchy
" + "{" +
" \"nodeId\": \"ns=2;s=Folder\" // Optional, omit for root" +
"}" +
"{" +
" \"success\": true," +
" \"children\": [" +
" {" +
" \"displayName\": \"Temperature\"," +
" \"nodeId\": \"ns=2;s=Temperature\"" +
" }" +
" ]" +
"}" +
"Browse complete OPC UA tree (server-side recursive)
" + "{" +
" \"maxDepth\": 5" +
"}" +
"{" +
" \"success\": true," +
" \"tree\": [...nested nodes...]," +
" \"duration\": 1234," +
" \"maxDepth\": 5" +
"}" +
"Use the API to integrate OPC UA data with external systems.
" + "// Read from OPC UA" +
"const opcResponse = await fetch('/api/read', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({nodeId: 'ns=2;s=Temperature'})" +
"});" +
"const opcData = await opcResponse.json();" +
"\n" +
"// Send to external system" +
"await fetch('https://api.example.com/data', {" +
" method: 'POST'," +
" headers: {" +
" 'Content-Type': 'application/json'," +
" 'Authorization': 'Bearer YOUR_TOKEN'" +
" }," +
" body: JSON.stringify({" +
" sensor: 'temperature'," +
" value: opcData.value," +
" timestamp: new Date().toISOString()" +
" })" +
"});" +
"// Login to external system" +
"const loginResponse = await fetch('https://api.example.com/auth/login', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({" +
" username: 'user'," +
" password: 'secret'" +
" })" +
"});" +
"const session = await loginResponse.json();" +
"\n" +
"// Store session for later use" +
"store.set('externalSession', session.token);" +
"store.set('externalExpiry', session.expiresAt);" +
"\n" +
"// Use in subsequent requests" +
"const token = store.get('externalSession');" +
"await fetch('https://api.example.com/data', {" +
" headers: {'Authorization': 'Bearer ' + token}" +
"});" +
"async function pollTemperature() {" +
" const response = await fetch('/api/read', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({nodeId: 'ns=2;s=Temperature'})" +
" });" +
" const data = await response.json();" +
" " +
" if (data.success) {" +
" console.log('Temperature:', data.value);" +
" " +
" // Send to external system" +
" await fetch('https://api.example.com/metrics', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({" +
" metric: 'temperature'," +
" value: parseFloat(data.value)" +
" })" +
" });" +
" }" +
"}" +
"\n" +
"// Poll every 5 seconds" +
"setInterval(pollTemperature, 5000);" +
"async function setSetpoint(value) {" +
" // Validate" +
" if (value < 0 || value > 100) {" +
" console.error('Value out of range');" +
" return;" +
" }" +
" " +
" // Write to OPC UA" +
" const response = await fetch('/api/write', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({" +
" nodeId: 'ns=2;s=SetPoint'," +
" value: value.toString()" +
" })" +
" });" +
" " +
" const result = await response.json();" +
" if (result.success && result.written) {" +
" console.log('Setpoint updated to', value);" +
" } else {" +
" console.error('Write failed');" +
" }" +
"}" +
"{" +
" \"success\": false," +
" \"error\": \"Error message\"" +
"}" +
"| Status | Error | Solution |
|---|---|---|
| 503 | OPC UA not connected | Check OPC UA connection |
| 400 | Invalid nodeId | Verify node ID format |
| 500 | Read/Write failed | Check node permissions |
Vollständige Referenz zur Integration mit der OPC UA HTTP API
" + "Die OPC UA HTTP API bietet RESTful Zugriff auf OPC UA Server Daten. Alle Endpunkte akzeptieren und liefern JSON.
" + "Basis-URL: http://localhost:8081
Content-Type: application/json
Aktuell ist keine Authentifizierung für lokalen Zugriff erforderlich. Für Produktionsumgebungen verwenden Sie HTTPS mit Client-Zertifikaten.
" + "OPC UA Verbindungsstatus abfragen
" + "{" +
" \"connected\": true," +
" \"timestamp\": 1707989123456" +
"}" +
"const response = await fetch('/api/status');" +
"const data = await response.json();" +
"console.log('Verbunden:', data.connected);" +
"Wert von einem OPC UA Knoten lesen
" + "{" +
" \"nodeId\": \"ns=2;s=Temperature\"" +
"}" +
"{" +
" \"success\": true," +
" \"value\": \"25.5\"," +
" \"timestamp\": 1707989123456" +
"}" +
"const response = await fetch('/api/read', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({nodeId: 'ns=2;s=Temperature'})" +
"});" +
"const data = await response.json();" +
"console.log('Temperatur:', data.value);" +
"Wert zu einem OPC UA Knoten schreiben
" + "{" +
" \"nodeId\": \"ns=2;s=SetPoint\"," +
" \"value\": \"30.0\"" +
"}" +
"{" +
" \"success\": true," +
" \"written\": true" +
"}" +
"const response = await fetch('/api/write', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({" +
" nodeId: 'ns=2;s=SetPoint'," +
" value: '30.0'" +
" })" +
"});" +
"const data = await response.json();" +
"console.log('Schreiben erfolgreich:', data.written);" +
"Verwenden Sie die API um OPC UA Daten mit externen Systemen zu integrieren.
" + "// Von OPC UA lesen" +
"const opcResponse = await fetch('/api/read', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({nodeId: 'ns=2;s=Temperature'})" +
"});" +
"const opcData = await opcResponse.json();" +
"\n" +
"// An externes System senden" +
"await fetch('https://api.example.com/data', {" +
" method: 'POST'," +
" headers: {" +
" 'Content-Type': 'application/json'," +
" 'Authorization': 'Bearer IHR_TOKEN'" +
" }," +
" body: JSON.stringify({" +
" sensor: 'temperatur'," +
" value: opcData.value," +
" timestamp: new Date().toISOString()" +
" })" +
"});" +
"// Bei externem System anmelden" +
"const loginResponse = await fetch('https://api.example.com/auth/login', {" +
" method: 'POST'," +
" headers: {'Content-Type': 'application/json'}," +
" body: JSON.stringify({" +
" username: 'benutzer'," +
" password: 'geheim'" +
" })" +
"});" +
"const session = await loginResponse.json();" +
"\n" +
"// Session für spätere Verwendung speichern" +
"store.set('externeSession', session.token);" +
"store.set('externeAblauf', session.expiresAt);" +
"\n" +
"// In nachfolgenden Requests verwenden" +
"const token = store.get('externeSession');" +
"await fetch('https://api.example.com/data', {" +
" headers: {'Authorization': 'Bearer ' + token}" +
"});" +
"{" +
" \"success\": false," +
" \"error\": \"Fehlermeldung\"" +
"}" +
"| Status | Fehler | Lösung |
|---|---|---|
| 503 | OPC UA nicht verbunden | OPC UA Verbindung prüfen |
| 400 | Ungültige nodeId | Node ID Format überprüfen |
| 500 | Lesen/Schreiben fehlgeschlagen | Node Berechtigungen prüfen |