aboutsummaryrefslogtreecommitdiff
path: root/templates/client.html
blob: 785fbcf953615012f7c2164b32092bf276390cd6 (plain)
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
<!DOCTYPE html>
<html>
<head>
    <title>Client {{ client_id }} - Camera Streams</title>
    <link rel="stylesheet" href="{{ url_for('static', path='css/main.css') }}">
    <style>
        .camera-stream { display: inline-block; margin: 10px; }
        video { border: 1px solid #333; }
    </style>
</head>
<body>
    <h1>Camera Streams for client: {{ client_id }}</h1>
    <div class="streams-container">
        {% for camera_id in camera_ids %}
        <div class="camera-stream">
            <h2>Camera: {{ camera_id }}</h2>
            <img
                id="video-{{ camera_id }}"
                width="640"
                height="480" />
            <div>
                <h3>Modify Camera Name</h3>
                <input
                    type="text"
                    id="new-name-{{ camera_id }}"
                    placeholder="New Name"
                    required pattern= "^\S+$"
                    title="No whitespace allowed.">
                <button onclick="sendConfig('{{ camera_id }}', 'modify_camera_name')">Send</button>
            </div>
            <div>
                <h3>Modify Camera Threshold</h3>
                <input
                    type="number"
                    id="threshold-value-{{ camera_id }}"
                    placeholder="Threshold"
                    required step="1"
                    min="0"
                    inputmode="numeric"
                    title="Enter a non-negative integer.">
                <button onclick="sendConfig('{{ camera_id }}', 'modify_camera_threshold')">Send</button>
            </div>
            <div>
                <h3>Modify Camera Grace Period</h3>
                <input
                    type="number"
                    id="grace-value-{{ camera_id }}"
                    placeholder="Grace Period"
                    required step="1"
                    min="0"
                    inputmode="numeric"
                    title="Enter a non-negative integer.">
                <button onclick="sendConfig('{{ camera_id }}', 'modify_camera_grace_pd')">Send</button>
            </div>
            <div>
                <h3>Recorded Videos for {{ camera_id }}</h3>
                <ul id="video-list-{{ camera_id }}" class="scroll-box">
                    {% for filename, video_url, timestamp in client_videos[camera_id] %}
                    <li><a href="{{ video_url }}">{{ filename }}</a> ({{ timestamp }})</li>
                    <!-- <h3>video file: {{ filename }}</h3>
                    <video src="{{ video_url }}" type="video/ogg" width="320" height="240" controls></video>
                    <hr4>creation: {{ timestamp }}</h3>
                    -->
                    {% endfor %}
                </ul>
            </div>
        </div>
        {% endfor %}
<!--
    <div>
        <h3>Add Camera</h3>
        <input type="text" id="add-name" placeholder="Camera Name">
        <input type="text" id="add-address" placeholder="Address">
        <button onclick="sendConfig('add_camera')">Send</button>
    </div>
-->
    <div>
        <h3>Remove Camera</h3>
        <input
            type="text"
            id="remove-name"
            placeholder="Camera Name"
            required pattern="^\S+$"
            title="No whitespace allowed.">
        <button onclick="sendConfig('remove_camera')">Send</button>
    </div>
    </div>
    <script>
    const wsMap = {};
    {% for camera_id in camera_ids %}
    // For each camera, open a WebSocket and update the corresponding <img>
    (function() {
        const cameraId = '{{ camera_id }}';
        const ws = new WebSocket('ws://' + window.location.host + '/ws/{{ client_id }}/' + cameraId);
        let currentUrl = null;
        ws.onmessage = function(event) {
            let image = document.getElementById('video-' + cameraId);
            if (currentUrl) {
                URL.revokeObjectURL(currentUrl);
            }
            currentUrl = URL.createObjectURL(event.data);
            image.src = currentUrl;
        };
        ws.onclose = function(event) {
            console.log('WebSocket closed for camera ' + cameraId + ':', event);
        };
        ws.onerror = function(event) {
            console.log('WebSocket error for camera ' + cameraId + ':', event);
        };
        window.addEventListener('beforeunload', function() {
            ws.close();
        });
        wsMap[cameraId] = ws;
    })();
    // FIXME: Move to a separate function
    // For each camera, open a WebSocket to receive notificationf about new videos
    // (function() {
    //     const cameraId = '{{ camera_id }}';
    //     const wsVideos = new WebSocket('ws://' + window.location.host + '/ws/{{ client_id }}/' + cameraId + '/videos');
    //     wsVideos.onmessage = function(event) {
    //         let videoFilename = event.data;
    //         console.log('New video available for camera ' + cameraId + ': ' + videoFilename);
    //         // On new video notification, 
    //     };
    // })();
    {% endfor %}

    function sendConfig(cameraId, type) {
        let msg = {};
        switch(type) {
            case 'modify_camera_name':
                msg[type] = [
                    document.getElementById('new-name-' + cameraId).value
                ];
                break;
            case 'modify_camera_threshold':
                msg[type] = [
                     document.getElementById('threshold-value-' + cameraId).value
                ];
                break;
            case 'modify_camera_grace_pd':
                msg[type] = [
                    parseInt(document.getElementById('grace-value-' + cameraId).value)
                ];
                break;
            case 'modify_camera_address':
                msg[type] = [
                    document.getElementById('address-value-' + cameraId).value
                ];
                break;
            // case 'add_camera':
            //     msg[type] = [
            //         document.getElementById('add-name').value,
            //         document.getElementById('add-address').value
            //     ];
            //     break;
            case 'remove_camera':
                msg[type] = [
                    document.getElementById('remove-name').value
                ];
                break;
        }
        const ws = wsMap[cameraId] && wsMap[cameraId] ? wsMap[cameraId] : Object.values(wsMap)[0];
        if (ws && ws.readyState === WebSocket.OPEN) {
            console.log("Sending message:", msg, "on ws:", ws);
            ws.send(JSON.stringify(msg));
        } else {
            alert('WebSocket is not open for camera ' + cameraId);
        }
    }
    </script>
</body>
</html>