Venus API question

Hi All,
Anyone using the Venus API to talk to their system remotely? I can hit the API endpoints using localhost and the PC’s IP address (from that PC, ie locally) - but I can’t access them from another PC. I checked the firewall rules and I can ping the PC’s IP address from another computer. I don’t have authentication turned on.

Any advice?

Thanks
Rob

Turns out you have to be not-dumb.

I was on a different network… The ping replies threw me off, but the networks were segregated. When I am on the right network, everything works as expected.

As an aside - Gemini (and I’m sure many of the other new models) is pretty amazing. I uploaded the API doc and asked for a simple monitor. Save the html below as a .html:

Venus Device Monitor /* Using Inter font from Google Fonts */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); body { font-family: 'Inter', sans-serif; background-color: #f3f4f6; /* A light gray background */ } /* Custom scrollbar for the trace log */ #trace-log::-webkit-scrollbar { width: 8px; } #trace-log::-webkit-scrollbar-track { background: #e5e7eb; border-radius: 10px; } #trace-log::-webkit-scrollbar-thumb { background: #9ca3af; border-radius: 10px; } #trace-log::-webkit-scrollbar-thumb:hover { background: #6b7280; }
<div class="container mx-auto p-4 md:p-8 max-w-4xl">
    <!-- Header -->
    <header class="mb-8">
        <h1 class="text-3xl font-bold text-gray-900">Venus Device Monitor</h1>
        <div class="flex items-center mt-2">
            <p class="text-gray-600 mr-2">Connection Status:</p>
            <span id="connection-status" class="px-3 py-1 text-sm font-semibold text-white bg-yellow-500 rounded-full">
                Connecting...
            </span>
        </div>
    </header>

    <!-- Main Content -->
    <main class="grid grid-cols-1 gap-8">
        <!-- Device Status Card -->
        <div class="bg-white p-6 rounded-xl shadow-md">
            <h2 class="text-xl font-semibold mb-4">Device Status</h2>
            <div class="flex items-center space-x-4">
                <div id="status-indicator-light" class="w-4 h-4 rounded-full bg-gray-400 animate-pulse"></div>
                <p id="device-status" class="text-lg font-medium text-gray-500">Waiting for status updates...</p>
            </div>
             <p id="status-message" class="text-sm text-gray-500 mt-2 ml-8"></p>
        </div>

        <!-- Real-time Trace Log Card -->
        <div class="bg-white p-6 rounded-xl shadow-md">
            <div class="flex justify-between items-center mb-4">
                <h2 class="text-xl font-semibold">Real-time Trace Log</h2>
                <button id="clear-log-btn" class="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-lg hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500">Clear Log</button>
            </div>
            <div id="trace-log" class="h-96 bg-gray-900 text-white font-mono text-sm p-4 rounded-lg overflow-y-auto">
                <!-- Trace messages will be appended here -->
                <div class="text-gray-400">Awaiting trace messages from the SignalR hub...</div>
            </div>
        </div>
    </main>

    <!-- Footer -->
    <footer class="text-center mt-8 text-sm text-gray-500">
        <p>Built for the Venus Web API. Connects to http://localhost:51745/signalR.</p>
    </footer>
</div>

<script>
    // --- DOM Element References ---
    const connectionStatusEl = document.getElementById('connection-status');
    const deviceStatusEl = document.getElementById('device-status');
    const statusMessageEl = document.getElementById('status-message');
    const statusIndicatorLightEl = document.getElementById('status-indicator-light');
    const traceLogEl = document.getElementById('trace-log');
    const clearLogBtn = document.getElementById('clear-log-btn');

    // --- Configuration ---
    const signalRUrl = "http://localhost:51745/signalR";

    // --- Status Mappings (Based on Programmer's Manual 4.3.3.2) ---
    const executorEventMap = {
        0: { text: "Undefined", color: "bg-gray-500" },
        1: { text: "Initialized", color: "bg-blue-500" },
        2: { text: "Initialization Failed", color: "bg-red-600" },
        3: { text: "Terminated", color: "bg-green-600" },
        4: { text: "Aborted", color: "bg-red-600" },
        5: { text: "Paused", color: "bg-yellow-500" },
        6: { text: "Running", color: "bg-green-500" },
        7: { text: "Unloaded", color: "bg-gray-500" }
    };

    // --- Helper Functions ---
    function updateConnectionStatus(status, color) {
        connectionStatusEl.textContent = status;
        connectionStatusEl.className = `px-3 py-1 text-sm font-semibold text-white ${color} rounded-full`;
    }

    function updateDeviceStatus(event, message) {
        const statusInfo = executorEventMap[event] || executorEventMap[0];
        
        deviceStatusEl.textContent = statusInfo.text;
        deviceStatusEl.classList.remove('text-gray-500');
        
        statusMessageEl.textContent = message || "No additional message.";
        
        // Update the status indicator light
        statusIndicatorLightEl.className = `w-4 h-4 rounded-full ${statusInfo.color}`;
        if (statusInfo.text === 'Running') {
            statusIndicatorLightEl.classList.add('animate-ping', 'opacity-75');
        } else {
             statusIndicatorLightEl.classList.remove('animate-ping', 'opacity-75', 'animate-pulse');
        }
    }

    function addTraceMessage(message) {
        // Clear the initial message if it exists
        if (traceLogEl.childElementCount === 1 && traceLogEl.firstChild.textContent.startsWith('Awaiting')) {
            traceLogEl.innerHTML = '';
        }

        const traceEntry = document.createElement('div');
        const timestamp = new Date().toLocaleTimeString();
        traceEntry.innerHTML = `<span class="text-gray-500 mr-2">${timestamp}</span><span class="text-green-400">&gt;</span> ${message}`;
        traceLogEl.appendChild(traceEntry);

        // Auto-scroll to the bottom
        traceLogEl.scrollTop = traceLogEl.scrollHeight;
    }
    
    clearLogBtn.addEventListener('click', () => {
         traceLogEl.innerHTML = '<div class="text-gray-400">Log cleared. Awaiting new trace messages...</div>';
    });

    // --- SignalR Connection Setup ---
    const connection = new signalR.HubConnectionBuilder()
        .withUrl(signalRUrl, {
            // As per the manual, these options might be necessary
            skipNegotiation: true,
            transport: signalR.HttpTransportType.WebSockets
        })
        .withAutomaticReconnect()
        .build();

    // --- SignalR Event Handlers ---

    // Handle "NewRuntimeStatus" push notification
    connection.on("NewRuntimeStatus", (data) => {
        console.log("NewRuntimeStatus:", data);
        if (data && typeof data.ExecutorEvent !== 'undefined') {
            updateDeviceStatus(data.ExecutorEvent, data.Message);
        }
    });

    // Handle "NewRuntimeTrace" push notification
    connection.on("NewRuntimeTrace", (data) => {
        console.log("NewRuntimeTrace:", data);
        addTraceMessage(data);
    });
    
    // Handle connection lifecycle events
    connection.onreconnecting(error => {
        console.warn(`Connection lost. Attempting to reconnect...`);
        updateConnectionStatus("Reconnecting", "bg-yellow-500");
    });

    connection.onreconnected(connectionId => {
        console.log(`Connection re-established. Connected with ID: ${connectionId}`);
        updateConnectionStatus("Connected", "bg-green-600");
    });

    connection.onclose(error => {
        console.error(`Connection closed due to error: "${error}". Try refreshing the page.`);
        updateConnectionStatus("Disconnected", "bg-red-600");
         statusIndicatorLightEl.className = 'w-4 h-4 rounded-full bg-red-600';
         statusIndicatorLightEl.classList.remove('animate-ping', 'opacity-75', 'animate-pulse');
    });


    // --- Start Connection ---
    async function start() {
        try {
            await connection.start();
            console.log("SignalR Connected.");
            updateConnectionStatus("Connected", "bg-green-600");
        } catch (err) {
            console.error("SignalR Connection Error: ", err);
            updateConnectionStatus("Failed", "bg-red-600");
            addTraceMessage(`ERROR: Could not connect to the SignalR hub at ${signalRUrl}. Ensure the Venus WebAPI Host service is running.`);
        }
    }

    start();

</script>
2 Likes