mirror of
https://github.com/PhotonVision/photonvision
synced 2026-07-06 03:31:41 +00:00
Added proper state machine to websocket video stream to control connect/disconnect sequence better. (#561)
This commit is contained in:
@@ -65,9 +65,9 @@
|
|||||||
disconnected(newVal, oldVal){
|
disconnected(newVal, oldVal){
|
||||||
oldVal;
|
oldVal;
|
||||||
if(newVal){
|
if(newVal){
|
||||||
this.wsStream.stopStream();
|
this.wsStream.setPort(0);
|
||||||
} else {
|
} else {
|
||||||
this.wsStream.startStream();
|
this.wsStream.setPort(this.port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -76,8 +76,7 @@
|
|||||||
this.wsStream = new wsvs.WebsocketVideoStream(this.id, this.port, window.location.host);
|
this.wsStream = new wsvs.WebsocketVideoStream(this.id, this.port, window.location.host);
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
this.wsStream.stopStream();
|
this.wsStream.setPort(0);
|
||||||
this.wsStream.ws_close();
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
reload() {
|
reload() {
|
||||||
|
|||||||
@@ -8,91 +8,184 @@ export class WebsocketVideoStream{
|
|||||||
this.drawDiv = drawDiv;
|
this.drawDiv = drawDiv;
|
||||||
this.image = document.getElementById(this.drawDiv);
|
this.image = document.getElementById(this.drawDiv);
|
||||||
this.streamPort = streamPort;
|
this.streamPort = streamPort;
|
||||||
|
this.newStreamPortReq = null;
|
||||||
this.serverAddr = "ws://" + host + "/websocket_cameras";
|
this.serverAddr = "ws://" + host + "/websocket_cameras";
|
||||||
this.noStream = false;
|
this.dispNoStream();
|
||||||
this.noStreamPrev = false;
|
|
||||||
this.setNoStream();
|
|
||||||
this.ws_connect();
|
this.ws_connect();
|
||||||
this.imgData = null;
|
this.imgData = null;
|
||||||
this.imgDataTime = -1;
|
this.imgDataTime = -1;
|
||||||
this.imgObjURL = null;
|
this.imgObjURL = null;
|
||||||
this.frameRxCount = 0;
|
this.frameRxCount = 0;
|
||||||
|
|
||||||
|
//Display state machine
|
||||||
|
this.DSM_DISCONNECTED = "DISCONNECTED";
|
||||||
|
this.DSM_WAIT_FOR_VALID_PORT = "WAIT_FOR_VALID_PORT";
|
||||||
|
this.DSM_SUBSCRIBE = "SUBSCRIBE";
|
||||||
|
this.DSM_WAIT_FOR_FIRST_FRAME = "WAIT_FOR_FIRST_FRAME";
|
||||||
|
this.DSM_SHOWING = "SHOWING";
|
||||||
|
this.DSM_RESTART_UNSUBSCRIBE = "UNSUBSCRIBE";
|
||||||
|
this.DSM_RESTART_WAIT = "WAIT_BEFORE_SUBSCRIBE";
|
||||||
|
|
||||||
|
this.dsm_cur_state = this.DSM_DISCONNECTED;
|
||||||
|
this.dsm_prev_state = this.DSM_DISCONNECTED;
|
||||||
|
this.dsm_restart_start_time = window.performance.now();
|
||||||
|
|
||||||
requestAnimationFrame(()=>this.animationLoop());
|
requestAnimationFrame(()=>this.animationLoop());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispImageData(){
|
||||||
|
//From https://stackoverflow.com/questions/67507616/set-image-src-from-image-blob/67507685#67507685
|
||||||
|
if(this.imgObjURL != null){
|
||||||
|
URL.revokeObjectURL(this.imgObjURL)
|
||||||
|
}
|
||||||
|
this.imgObjURL = URL.createObjectURL(this.imgData);
|
||||||
|
|
||||||
|
//Update the image with the new mimetype and image
|
||||||
|
this.image.src = this.imgObjURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispNoStream() {
|
||||||
|
this.image.src = require("../assets/loading.gif");
|
||||||
|
}
|
||||||
|
|
||||||
animationLoop(){
|
animationLoop(){
|
||||||
|
// Update time metrics
|
||||||
var now = window.performance.now();
|
var now = window.performance.now();
|
||||||
|
var timeInState = now - this.dsm_restart_start_time;
|
||||||
|
|
||||||
if((now - this.imgDataTime) > 2500 && this.imgData != null){
|
// Save previous state
|
||||||
//Handle websocket send timeouts by restarting
|
this.dsm_prev_state = this.dsm_cur_state;
|
||||||
this.setNoStream();
|
|
||||||
this.stopStream();
|
// Evaluate state transitions
|
||||||
setTimeout(this.startStream.bind(this), 1000); //restart stream one second later
|
if(this.serverConnectionActive == false){
|
||||||
|
//Any state - if the server connection goes false, always transition to disconnected
|
||||||
|
this.dsm_cur_state = this.DSM_DISCONNECTED;
|
||||||
} else {
|
} else {
|
||||||
if(this.streamPort == null){
|
//Conditional transitions
|
||||||
this.setNoStream();
|
switch(this.dsm_cur_state) {
|
||||||
} else if (this.imgData != null) {
|
case this.DSM_DISCONNECTED:
|
||||||
//From https://stackoverflow.com/questions/67507616/set-image-src-from-image-blob/67507685#67507685
|
//Immediately transition to waiting for the first frame
|
||||||
if(this.imgObjURL != null){
|
this.dsm_cur_state = this.DSM_WAIT_FOR_VALID_PORT;
|
||||||
URL.revokeObjectURL(this.imgObjURL)
|
break;
|
||||||
}
|
case this.DSM_WAIT_FOR_VALID_PORT:
|
||||||
this.imgObjURL = URL.createObjectURL(this.imgData);
|
// Wait until the user has configured a valid port
|
||||||
|
if(this.streamPort > 0){
|
||||||
//Update the image with the new mimetype and image
|
this.dsm_cur_state = this.DSM_SUBSCRIBE;
|
||||||
this.image.src = this.imgObjURL;
|
} else {
|
||||||
this.noStream = false;
|
this.dsm_cur_state = this.DSM_WAIT_FOR_VALID_PORT;
|
||||||
|
}
|
||||||
} else {
|
break;
|
||||||
//Nothing, hold previous image while waiting for next frame
|
case this.DSM_SUBSCRIBE:
|
||||||
}
|
// Immediately transition after subscriptions is sent
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_FIRST_FRAME;
|
||||||
|
break;
|
||||||
|
case this.DSM_WAIT_FOR_FIRST_FRAME:
|
||||||
|
if(this.imgData != null){
|
||||||
|
//we got some image data, start showing it
|
||||||
|
this.dsm_cur_state = this.DSM_SHOWING;
|
||||||
|
} else if (this.newStreamPortReq != null){
|
||||||
|
//Stream port requested changed, unsubscribe and restart
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_UNSUBSCRIBE;
|
||||||
|
} else {
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_FIRST_FRAME;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case this.DSM_SHOWING:
|
||||||
|
if((now - this.imgDataTime) > 2500){
|
||||||
|
//timeout, begin the restart sequence
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_UNSUBSCRIBE;
|
||||||
|
} else if (this.newStreamPortReq != null){
|
||||||
|
//Stream port requested changed, unsubscribe and restart
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_UNSUBSCRIBE;
|
||||||
|
} else {
|
||||||
|
//stay in this state.
|
||||||
|
this.dsm_cur_state = this.DSM_SHOWING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case this.DSM_RESTART_UNSUBSCRIBE:
|
||||||
|
//Only should spend one loop in Unsubscribe, immediately transition
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_WAIT;
|
||||||
|
break;
|
||||||
|
case this.DSM_RESTART_WAIT:
|
||||||
|
if (timeInState > 250) {
|
||||||
|
//we've waited long enough, go to try to re-subscribe
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_VALID_PORT;
|
||||||
|
} else {
|
||||||
|
//stay in this state.
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_WAIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Shouldn't get here, default back to init
|
||||||
|
this.dsm_cur_state = this.DSM_DISCONNECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//take current-state or state-transition actions
|
||||||
|
|
||||||
|
if(this.dsm_cur_state != this.dsm_prev_state){
|
||||||
|
//Any state transition
|
||||||
|
console.log("State Change: " + this.dsm_prev_state + " -> " + this.dsm_cur_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_SHOWING){
|
||||||
|
// Currently in SHOWING
|
||||||
|
this.dispImageData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state != this.DSM_SHOWING && this.dsm_prev_state == this.DSM_SHOWING ){
|
||||||
|
//Any transition out of showing - no stream
|
||||||
|
this.dispNoStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_RESTART_UNSUBSCRIBE){
|
||||||
|
// Currently in UNSUBSCRIBE, do the unsubscribe actions
|
||||||
|
this.stopStream();
|
||||||
|
this.dsm_restart_start_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_SUBSCRIBE){
|
||||||
|
// Currently in SUBSCRIBE, do the subscribe actions
|
||||||
|
this.startStream();
|
||||||
|
this.dsm_restart_start_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_WAIT_FOR_VALID_PORT){
|
||||||
|
// Currently waiting for a vaild port to be requested
|
||||||
|
if(this.newStreamPortReq != null){
|
||||||
|
this.streamPort = this.newStreamPortReq;
|
||||||
|
this.newStreamPortReq = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requestAnimationFrame(()=>this.animationLoop());
|
requestAnimationFrame(()=>this.animationLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
setNoStream() {
|
|
||||||
this.noStreamPrev = this.noStream;
|
|
||||||
this.noStream = true;
|
|
||||||
if(this.noStreamPrev == false && this.noStream == true){
|
|
||||||
//One-shot background change to preserve animation
|
|
||||||
this.image.src = require("../assets/loading.gif");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startStream() {
|
startStream() {
|
||||||
if(this.serverConnectionActive == true && this.streamPort > 0){
|
console.log("Subscribing to port " + this.streamPort);
|
||||||
this.ws.send(JSON.stringify({"cmd": "subscribe", "port":this.streamPort}));
|
this.imgData = null;
|
||||||
this.noStream = false;
|
this.ws.send(JSON.stringify({"cmd": "subscribe", "port":this.streamPort}));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stopStream() {
|
stopStream() {
|
||||||
if(this.serverConnectionActive == true && this.streamPort > 0){
|
console.log("Unsubscribing");
|
||||||
this.ws.send(JSON.stringify({"cmd": "unsubscribe"}));
|
this.ws.send(JSON.stringify({"cmd": "unsubscribe"}));
|
||||||
this.noStream = true;
|
this.imgData = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPort(streamPort){
|
setPort(streamPort){
|
||||||
this.stopStream();
|
console.log("Port set to " + streamPort);
|
||||||
this.frameRxCount = 0;
|
this.newStreamPortReq = streamPort;
|
||||||
this.streamPort = streamPort;
|
|
||||||
this.startStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_onOpen() {
|
ws_onOpen() {
|
||||||
// Set the flag allowing general server communication
|
// Set the flag allowing general server communication
|
||||||
this.serverConnectionActive = true;
|
this.serverConnectionActive = true;
|
||||||
console.log("Connected!");
|
console.log("Camera Websockets Connected!");
|
||||||
this.startStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_onClose(e) {
|
ws_onClose(e) {
|
||||||
this.setNoStream();
|
|
||||||
|
|
||||||
//Clear flags to stop server communication
|
//Clear flags to stop server communication
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
this.serverConnectionActive = false;
|
this.serverConnectionActive = false;
|
||||||
@@ -129,6 +222,7 @@ export class WebsocketVideoStream{
|
|||||||
}
|
}
|
||||||
|
|
||||||
ws_connect() {
|
ws_connect() {
|
||||||
|
this.serverConnectionActive = false;
|
||||||
this.ws = new WebSocket(this.serverAddr);
|
this.ws = new WebSocket(this.serverAddr);
|
||||||
this.ws.binaryType = "blob";
|
this.ws.binaryType = "blob";
|
||||||
this.ws.onopen = this.ws_onOpen.bind(this);
|
this.ws.onopen = this.ws_onOpen.bind(this);
|
||||||
|
|||||||
@@ -69,10 +69,13 @@ public class SocketVideoStreamManager {
|
|||||||
// Indicate a user would like to stop receiving one camera stream
|
// Indicate a user would like to stop receiving one camera stream
|
||||||
public void removeSubscription(WsContext user) {
|
public void removeSubscription(WsContext user) {
|
||||||
var port = userSubscriptions.get(user);
|
var port = userSubscriptions.get(user);
|
||||||
if (port != null) {
|
if (port != null && port != NO_STREAM_PORT) {
|
||||||
var stream = streams.get(port);
|
var stream = streams.get(port);
|
||||||
userSubscriptions.put(user, NO_STREAM_PORT);
|
userSubscriptions.put(user, NO_STREAM_PORT);
|
||||||
stream.removeUser();
|
stream.removeUser();
|
||||||
|
} else {
|
||||||
|
logger.error(
|
||||||
|
"User attempted to unsubscribe, but had not yet previously subscribed successfully.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,89 +45,183 @@
|
|||||||
this.drawDiv = drawDiv;
|
this.drawDiv = drawDiv;
|
||||||
this.image = document.getElementById(this.drawDiv);
|
this.image = document.getElementById(this.drawDiv);
|
||||||
this.streamPort = streamPort;
|
this.streamPort = streamPort;
|
||||||
|
this.newStreamPortReq = null;
|
||||||
this.serverAddr = "ws://" + host + "/websocket_cameras";
|
this.serverAddr = "ws://" + host + "/websocket_cameras";
|
||||||
this.noStream = false;
|
this.dispNoStream();
|
||||||
this.noStreamPrev = false;
|
|
||||||
this.setNoStream();
|
|
||||||
this.ws_connect();
|
this.ws_connect();
|
||||||
this.imgData = null;
|
this.imgData = null;
|
||||||
this.imgDataTime = -1;
|
this.imgDataTime = -1;
|
||||||
this.imgObjURL = null;
|
this.imgObjURL = null;
|
||||||
this.frameRxCount = 0;
|
this.frameRxCount = 0;
|
||||||
|
|
||||||
|
//Display state machine
|
||||||
|
this.DSM_DISCONNECTED = "DISCONNECTED";
|
||||||
|
this.DSM_WAIT_FOR_VALID_PORT = "WAIT_FOR_VALID_PORT";
|
||||||
|
this.DSM_SUBSCRIBE = "SUBSCRIBE";
|
||||||
|
this.DSM_WAIT_FOR_FIRST_FRAME = "WAIT_FOR_FIRST_FRAME";
|
||||||
|
this.DSM_SHOWING = "SHOWING";
|
||||||
|
this.DSM_RESTART_UNSUBSCRIBE = "UNSUBSCRIBE";
|
||||||
|
this.DSM_RESTART_WAIT = "WAIT_BEFORE_SUBSCRIBE";
|
||||||
|
|
||||||
|
this.dsm_cur_state = this.DSM_DISCONNECTED;
|
||||||
|
this.dsm_prev_state = this.DSM_DISCONNECTED;
|
||||||
|
this.dsm_restart_start_time = window.performance.now();
|
||||||
|
|
||||||
requestAnimationFrame(()=>this.animationLoop());
|
requestAnimationFrame(()=>this.animationLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispImageData(){
|
||||||
|
//From https://stackoverflow.com/questions/67507616/set-image-src-from-image-blob/67507685#67507685
|
||||||
|
if(this.imgObjURL != null){
|
||||||
|
URL.revokeObjectURL(this.imgObjURL)
|
||||||
|
}
|
||||||
|
this.imgObjURL = URL.createObjectURL(this.imgData);
|
||||||
|
|
||||||
|
//Update the image with the new mimetype and image
|
||||||
|
this.image.src = this.imgObjURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispNoStream() {
|
||||||
|
this.image.src = "loading.gif";
|
||||||
|
}
|
||||||
|
|
||||||
animationLoop(){
|
animationLoop(){
|
||||||
|
// Update time metrics
|
||||||
var now = window.performance.now();
|
var now = window.performance.now();
|
||||||
|
var timeInState = now - this.dsm_restart_start_time;
|
||||||
|
|
||||||
if((now - this.imgDataTime) > 2500 && this.imgData != null){
|
// Save previous state
|
||||||
//Handle websocket send timeouts by restarting
|
this.dsm_prev_state = this.dsm_cur_state;
|
||||||
this.setNoStream();
|
|
||||||
this.stopStream();
|
// Evaluate state transitions
|
||||||
setTimeout(this.startStream.bind(this), 1000); //restart stream one second later
|
if(this.serverConnectionActive == false){
|
||||||
|
//Any state - if the server connection goes false, always transition to disconnected
|
||||||
|
this.dsm_cur_state = this.DSM_DISCONNECTED;
|
||||||
} else {
|
} else {
|
||||||
if(this.streamPort == null){
|
//Conditional transitions
|
||||||
this.setNoStream();
|
switch(this.dsm_cur_state) {
|
||||||
} else if (this.imgData != null) {
|
case this.DSM_DISCONNECTED:
|
||||||
//From https://stackoverflow.com/questions/67507616/set-image-src-from-image-blob/67507685#67507685
|
//Immediately transition to waiting for the first frame
|
||||||
if(this.imgObjURL != null){
|
this.dsm_cur_state = this.DSM_WAIT_FOR_VALID_PORT;
|
||||||
URL.revokeObjectURL(this.imgObjURL)
|
break;
|
||||||
}
|
case this.DSM_WAIT_FOR_VALID_PORT:
|
||||||
this.imgObjURL = URL.createObjectURL(this.imgData);
|
// Wait until the user has configured a valid port
|
||||||
|
if(this.streamPort > 0){
|
||||||
|
this.dsm_cur_state = this.DSM_SUBSCRIBE;
|
||||||
|
} else {
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_VALID_PORT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case this.DSM_SUBSCRIBE:
|
||||||
|
// Immediately transition after subscriptions is sent
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_FIRST_FRAME;
|
||||||
|
break;
|
||||||
|
case this.DSM_WAIT_FOR_FIRST_FRAME:
|
||||||
|
if(this.imgData != null){
|
||||||
|
//we got some image data, start showing it
|
||||||
|
this.dsm_cur_state = this.DSM_SHOWING;
|
||||||
|
} else if (this.newStreamPortReq != null){
|
||||||
|
//Stream port requested changed, unsubscribe and restart
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_UNSUBSCRIBE;
|
||||||
|
} else {
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_FIRST_FRAME;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case this.DSM_SHOWING:
|
||||||
|
if((now - this.imgDataTime) > 2500){
|
||||||
|
//timeout, begin the restart sequence
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_UNSUBSCRIBE;
|
||||||
|
} else if (this.newStreamPortReq != null){
|
||||||
|
//Stream port requested changed, unsubscribe and restart
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_UNSUBSCRIBE;
|
||||||
|
} else {
|
||||||
|
//stay in this state.
|
||||||
|
this.dsm_cur_state = this.DSM_SHOWING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case this.DSM_RESTART_UNSUBSCRIBE:
|
||||||
|
//Only should spend one loop in Unsubscribe, immediately transition
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_WAIT;
|
||||||
|
break;
|
||||||
|
case this.DSM_RESTART_WAIT:
|
||||||
|
if (timeInState > 250) {
|
||||||
|
//we've waited long enough, go to try to re-subscribe
|
||||||
|
this.dsm_cur_state = this.DSM_WAIT_FOR_VALID_PORT;
|
||||||
|
} else {
|
||||||
|
//stay in this state.
|
||||||
|
this.dsm_cur_state = this.DSM_RESTART_WAIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Shouldn't get here, default back to init
|
||||||
|
this.dsm_cur_state = this.DSM_DISCONNECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Update the image with the new mimetype and image
|
//take current-state or state-transition actions
|
||||||
this.image.src = this.imgObjURL;
|
|
||||||
this.noStream = false;
|
|
||||||
|
|
||||||
} else {
|
if(this.dsm_cur_state != this.dsm_prev_state){
|
||||||
//Nothing, hold previous image while waiting for next frame
|
//Any state transition
|
||||||
|
console.log("State Change: " + this.dsm_prev_state + " -> " + this.dsm_cur_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_SHOWING){
|
||||||
|
// Currently in SHOWING
|
||||||
|
this.dispImageData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state != this.DSM_SHOWING && this.dsm_prev_state == this.DSM_SHOWING ){
|
||||||
|
//Any transition out of showing - no stream
|
||||||
|
this.dispNoStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_RESTART_UNSUBSCRIBE){
|
||||||
|
// Currently in UNSUBSCRIBE, do the unsubscribe actions
|
||||||
|
this.stopStream();
|
||||||
|
this.dsm_restart_start_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_SUBSCRIBE){
|
||||||
|
// Currently in SUBSCRIBE, do the subscribe actions
|
||||||
|
this.startStream();
|
||||||
|
this.dsm_restart_start_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.dsm_cur_state == this.DSM_WAIT_FOR_VALID_PORT){
|
||||||
|
// Currently waiting for a vaild port to be requested
|
||||||
|
if(this.newStreamPortReq != null){
|
||||||
|
this.streamPort = this.newStreamPortReq;
|
||||||
|
this.newStreamPortReq = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(()=>this.animationLoop());
|
requestAnimationFrame(()=>this.animationLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
setNoStream() {
|
|
||||||
this.noStreamPrev = this.noStream;
|
|
||||||
this.noStream = true;
|
|
||||||
if(this.noStreamPrev == false && this.noStream == true){
|
|
||||||
//One-shot background change to preserve animation
|
|
||||||
this.image.src = "loading.gif";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startStream() {
|
startStream() {
|
||||||
if(this.serverConnectionActive == true && this.streamPort > 0){
|
console.log("Subscribing to port " + this.streamPort);
|
||||||
this.ws.send(JSON.stringify({"cmd": "subscribe", "port":this.streamPort}));
|
this.imgData = null;
|
||||||
this.noStream = false;
|
this.ws.send(JSON.stringify({"cmd": "subscribe", "port":this.streamPort}));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stopStream() {
|
stopStream() {
|
||||||
if(this.serverConnectionActive == true && this.streamPort > 0){
|
console.log("Unsubscribing");
|
||||||
this.ws.send(JSON.stringify({"cmd": "unsubscribe"}));
|
this.ws.send(JSON.stringify({"cmd": "unsubscribe"}));
|
||||||
this.noStream = true;
|
this.imgData = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPort(streamPort){
|
setPort(streamPort){
|
||||||
this.stopStream();
|
console.log("Port set to " + streamPort);
|
||||||
this.frameRxCount = 0;
|
this.newStreamPortReq = streamPort;
|
||||||
this.streamPort = streamPort;
|
|
||||||
this.startStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_onOpen() {
|
ws_onOpen() {
|
||||||
// Set the flag allowing general server communication
|
// Set the flag allowing general server communication
|
||||||
this.serverConnectionActive = true;
|
this.serverConnectionActive = true;
|
||||||
console.log("Connected!");
|
console.log("Connected!");
|
||||||
this.startStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ws_onClose(e) {
|
ws_onClose(e) {
|
||||||
this.setNoStream();
|
|
||||||
|
|
||||||
//Clear flags to stop server communication
|
//Clear flags to stop server communication
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
this.serverConnectionActive = false;
|
this.serverConnectionActive = false;
|
||||||
@@ -165,6 +259,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
ws_connect() {
|
ws_connect() {
|
||||||
|
this.serverConnectionActive = false;
|
||||||
this.ws = new WebSocket(this.serverAddr);
|
this.ws = new WebSocket(this.serverAddr);
|
||||||
this.ws.binaryType = "blob";
|
this.ws.binaryType = "blob";
|
||||||
this.ws.onopen = this.ws_onOpen.bind(this);
|
this.ws.onopen = this.ws_onOpen.bind(this);
|
||||||
@@ -187,7 +282,6 @@
|
|||||||
var port = document.getElementById("port").value;
|
var port = document.getElementById("port").value;
|
||||||
if(stream == null){
|
if(stream == null){
|
||||||
stream = new WebsocketVideoStream("streamImg",port,host);
|
stream = new WebsocketVideoStream("streamImg",port,host);
|
||||||
stream.startStream();
|
|
||||||
} else {
|
} else {
|
||||||
stream.setPort(port);
|
stream.setPort(port);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user