public void OnDataAvailable(SensorDataPacket packet) { HandleTimeout(); if (IsCancelled) { return; } if (packet.DataType != SensorDataType.Video) { // only video data supported return; } var frame = packet.GenericData as VideoFrame; if (frame == null) { // unsupported content return; } // generate a base64 string from the video frame string imageString = string.Empty; if (includeImage) { imageString = CompressImage(frame); } // craete a message that contains the compressed image // and send it through the consumer to the client var message = new JsonString(messageTemplate); var subject = JsonString.CreateDict(); { subject.AddTerminal("type", JsonString.StringifyString("post")); subject.AddTerminal("topic", JsonString.StringifyString("sensorCapture")); subject.AddTerminal("position", JsonString.Stringify(sensorIndex)); var dataArray = JsonString.CreateArray(); { var dataEntry = JsonString.CreateDict(); { if (includeImage && imageString.Length > 2) { dataEntry.AddTerminal("image", imageString); } dataEntry.AddTerminal("frameWidth", JsonString.Stringify(frame.Width)); dataEntry.AddTerminal("frameHeight", JsonString.Stringify(frame.Height)); var metadata = frame.Metadata; dataEntry.AddTerminal("frameRate", JsonString.Stringify(metadata.FrameRate)); dataEntry.AddTerminal("frameTime", JsonString.Stringify(metadata.FrameTime)); dataEntry.AddTerminal("frameTimeDeviation", JsonString.Stringify(metadata.FrameTimeDeviation)); } dataArray.AddJsonString(string.Empty, dataEntry); } subject.AddJsonString("data", dataArray); } message.AddJsonString("subject", subject); string str = message.ToJsonString(); consumer.EnqueueMessage(message); }
public override HttpStatusCode Respond(JsonString subject, JsonString response) { if (subject == null) { throw new ArgumentNullException("subject"); } if (response == null) { throw new ArgumentNullException("response"); } bool isGetRequest; string type = JsonString.ParseString(subject.GetTerminal("type", "error"), "error"); if (type.Equals("get")) { isGetRequest = true; } else if (type.Equals("post")) { isGetRequest = false; } else { return(HttpStatusCode.BadRequest); } int[] positions = ReadPosition(subject); if (positions == null) { return(HttpStatusCode.BadRequest); } var responseSubject = JsonString.CreateDict(); { responseSubject.AddTerminal("type", JsonString.StringifyString("post")); responseSubject.AddTerminal("topic", JsonString.StringifyString("tracker")); } response.AddJsonString("subject", responseSubject); if (isGetRequest) { return(RespondGet(subject, responseSubject, positions)); } else { HttpStatusCode status = RespondPost(subject, responseSubject, positions); // not only send the result to one recipient but create an update for all clients if (status == HttpStatusCode.OK) { var update = new JsonString(response); update.RemoveTerminal("requestId"); update.AddTerminal("target", "\"all\""); server.PostUpdate(update); } return(status); } }
private void CreateErrorResponse(JsonString request, JsonString response, HttpStatusCode status) { // add status code information if (response.Type == JsonStringType.Array) { // unexpected -> give minimal response var error = JsonString.CreateDict(); error.AddTerminal("status", JsonString.Stringify((int)status)); response.AddJsonString(string.Empty, error); return; } response.AddTerminal("status", JsonString.Stringify((int)status)); // add the original message to failed updates // that way it is easier to recognize the failed operation if (response.GetTerminal("requestId", string.Empty).Length == 0) { response.AddJsonString("request", new JsonString(request)); } }
private HttpStatusCode RespondGet(JsonString requestSubject, JsonString responseSubject, int sensorStart, int sensorEnd) { object dataSync = new object(); JsonString data; lock (dataSync) { // TODO lock required? data = JsonString.CreateArray(); } var readySignal = new ManualResetEvent(false); CaptureSystem.Instance.Invoke((object sender, EventArgs args) => { var system = (CaptureSystem)sender; for (int i = sensorStart; i <= sensorEnd; i++) { var entry = JsonString.CreateDict(); ISensorBase sensor = system.GetSensor(i); if (sensor == null) { entry.AddTerminal("inuse", "false"); } else if (sensor.SensorType == SensorType.Webcam) { var capture = (WebcamCapture)sensor; EquipmentSettings settings = capture.GetSettings(); entry.AddTerminal("inuse", "true"); entry.AddJsonString("settings", EquipmentSettings.ToJson(settings)); } else { entry.AddTerminal("inuse", "false"); } data.AddJsonString(string.Empty, entry); } readySignal.Set(); }); readySignal.WaitOne(); lock (dataSync) { responseSubject.AddJsonString("data", data); } return(HttpStatusCode.OK); }
public HttpStatusCode Respond(JsonString subject, JsonString response) { if (subject == null) { throw new ArgumentNullException("subject"); } if (response == null) { throw new ArgumentNullException("response"); } // send the client and server origin ids as subject // while the type must be 'get' which is answered with 'post' HttpStatusCode status = HttpStatusCode.OK; do { string type = JsonString.ParseString(subject.GetTerminal("type", "error"), "error"); if (!type.Equals("get")) { status = HttpStatusCode.Forbidden; break; } response.AddTerminal("origin", JsonString.Stringify(serverOrigin)); var rSubject = JsonString.CreateDict(); { rSubject.AddTerminal("type", JsonString.StringifyString("post")); rSubject.AddTerminal("topic", JsonString.StringifyString("origin")); var data = JsonString.CreateDict(); { data.AddTerminal("serverOrigin", JsonString.Stringify(serverOrigin)); data.AddTerminal("clientOrigin", JsonString.Stringify(clientOrigin)); } rSubject.AddJsonString("data", data); } response.AddJsonString("subject", rSubject); } while (false); return(status); }
private HttpStatusCode RespondGet(JsonString requestSubject, JsonString responseSubject, int[] positions) { object dataSync = new object(); JsonString data; lock (dataSync) { // TODO lock required? data = JsonString.CreateDict(); } var readySignal = new ManualResetEvent(false); TrackingSystem.Instance.Invoke((object sender, EventArgs args) => { var system = (TrackingSystem)sender; foreach (int pos in positions) { var entry = JsonString.CreateDict(); IPoseTracker tracker = system.GetTracker(pos); if (tracker == null) { entry.AddTerminal("inuse", "false"); } else if (tracker is P3CapTracker) { var capTracker = (P3CapTracker)tracker; EquipmentSettings settings = capTracker.GetSettings(); entry.AddTerminal("inuse", "true"); entry.AddJsonString("settings", EquipmentSettings.ToJson(settings)); } data.AddJsonString(JsonString.Stringify(pos), entry); } readySignal.Set(); }); readySignal.WaitOne(); lock (dataSync) { responseSubject.AddJsonString("data", data); } return(HttpStatusCode.OK); }
public HttpStatusCode Respond(JsonString subject, JsonString response) { if (subject == null) { throw new ArgumentNullException("subject"); } if (response == null) { throw new ArgumentNullException("response"); } int sensorStart = -2; int sensorEnd = 0; bool isGetRequest; string type = JsonString.ParseString(subject.GetTerminal("type", "error"), "error"); if (type.Equals("get")) { isGetRequest = true; } else if (type.Equals("post")) { isGetRequest = false; } else { return(HttpStatusCode.BadRequest); } string position = JsonString.ParseString(subject.GetTerminal("position", "all"), "all"); if (position.Equals("all")) { sensorStart = 0; sensorEnd = 15; // TODO replace with actual capacity } else { sensorStart = JsonString.ParseInt(position, -1); sensorEnd = sensorStart; } if (sensorStart < 0) { return(HttpStatusCode.NotFound); } var responseSubject = JsonString.CreateDict(); responseSubject.AddTerminal("type", JsonString.StringifyString("post")); responseSubject.AddTerminal("topic", JsonString.StringifyString("camera")); responseSubject.AddTerminal("position", JsonString.StringifyString(position)); response.AddJsonString("subject", responseSubject); if (isGetRequest) { return(RespondGet(subject, responseSubject, sensorStart, sensorEnd)); } else { if (sensorStart != sensorEnd) { return(HttpStatusCode.BadRequest); } HttpStatusCode status = RespondPost(subject, responseSubject, sensorStart); // not only send the result to one recipient but create an update for all clients if (status == HttpStatusCode.OK) { var update = new JsonString(response); update.RemoveTerminal("requestId"); update.AddTerminal("target", "\"all\""); server.PostUpdate(update); } return(status); } }
private HttpStatusCode RespondPost(JsonString requestSubject, JsonString responseSubject, int sensorIndex) { object dataSync = new object(); // first read the data from the data array JsonString data = requestSubject.GetJsonString("data"); if (data == null || data.Type != JsonStringType.Array || data.Array.Count < 1) { return(HttpStatusCode.BadRequest); } var targetMap = new Dictionary <int, EquipmentSettings>(); for (int i = 0; i <= 0; i++) { JsonString sensor = data.GetJsonString(0); if (sensor == null) { return(HttpStatusCode.BadRequest); } bool used = JsonString.ParseBool(sensor.GetTerminal("inuse", "false"), false); if (used) { JsonString jSettings = sensor.GetJsonString("settings"); if (jSettings == null) { return(HttpStatusCode.BadRequest); } var settings = EquipmentSettings.FromJson(jSettings, typeof(SensorProperty)); targetMap.Add(sensorIndex + i, settings); } } // secondly satisfy the request var status = HttpStatusCode.OK; var resultMap = new Dictionary <int, EquipmentSettings>(); var readySignal = new ManualResetEvent(false); CaptureSystem.Instance.Invoke((object sender, EventArgs args) => { var system = (CaptureSystem)sender; for (int iSource = sensorIndex; iSource <= sensorIndex; iSource++) { // first determine which operations to perform int iTarget = iSource; bool connect = false; bool disconnect = false; bool start = false; bool stop = false; bool apply = false; var entry = data.GetJsonString(0); ISensorBase sensor = system.GetSensor(sensorIndex); EquipmentSettings sourceSettings = null; SensorType sourceType = SensorType.Webcam; if (sensor != null) { sourceSettings = ((WebcamCapture)sensor).GetSettings(); int iType = sourceSettings.GetInteger(SensorProperty.Type, -1); if (iType > -1) { sourceType = (SensorType)iType; } } EquipmentSettings targetSettings = null; SensorType targetType = SensorType.Webcam; if (targetMap.TryGetValue(iSource, out targetSettings)) { int iType = targetSettings.GetInteger(SensorProperty.Type, -1); if (iType > -1) { targetType = (SensorType)iType; } } if (sourceSettings == null && targetSettings != null) { connect = true; } else if (sourceSettings != null && targetSettings == null) { disconnect = true; } else if (sourceSettings == null && targetSettings == null) { // nothing to do } else { if (sourceType != targetType) { disconnect = true; connect = true; } apply = true; } if (targetSettings != null) { int iTargetCapturing = targetSettings.GetInteger(SensorProperty.Capturing, -1); if (iTargetCapturing < 0) { // ignore if not available } else if (iTargetCapturing != 0) { start = true; } else { stop = true; } } // TODO make restrictions or otherwise cover remaining possible cases bool success = true; // perform the operations which were activated above if (disconnect && success) { if (system.DisconnectSensor(iSource)) { LogManager.Instance.LogMessage(this, "Disconnected sensor " + iSource); sensor = null; // already removed from result map } else { // nothing changed LogManager.Instance.LogError(this, "Failed to disconnect sensor " + iSource); resultMap[iSource] = sourceSettings; success = false; } } if (connect && success) { sensor = new WebcamCapture(targetSettings); int iNext = system.ConnectSensor(sensor, iTarget); if (iNext == iTarget) { LogManager.Instance.LogMessage(this, "Connected sensor " + iNext); targetSettings = ((WebcamCapture)sensor).GetSettings(); resultMap[iTarget] = targetSettings; } else if (iNext < 0) { // failed, leave result map entry empty LogManager.Instance.LogError(this, "Failed to connect new sensor"); sensor = null; success = false; } else { LogManager.Instance.LogMessage(this, "Connected sensor " + iNext); // sensor connected with different index, which we can accept iTarget = iNext; resultMap[iNext] = targetSettings; targetSettings = ((WebcamCapture)sensor).GetSettings(); } } if (stop && success) { if (system.StopSensor(iTarget)) { LogManager.Instance.LogMessage(this, "Stopped sensor " + iTarget); } else { targetSettings = ((WebcamCapture)sensor).GetSettings(); success = false; LogManager.Instance.LogError(this, "Failed to stop sensor " + iTarget); } resultMap[iTarget] = targetSettings; } if (apply && success) { if (sensor != null) { if (((WebcamCapture)sensor).ApplySettings(targetSettings)) { LogManager.Instance.LogMessage(this, "Applied new settings to sensor " + iTarget); } else { LogManager.Instance.LogError(this, "Failed to apply new settings to sensor " + iTarget); } targetSettings = ((WebcamCapture)sensor).GetSettings(); resultMap[iTarget] = targetSettings; } } if (start && success) { if (system.StartSensor(iSource)) { LogManager.Instance.LogMessage(this, "Started sensor " + iSource); targetSettings = ((WebcamCapture)sensor).GetSettings(); resultMap[iTarget] = targetSettings; } else { LogManager.Instance.LogError(this, "Failed to start sensor " + iSource); targetSettings = ((WebcamCapture)sensor).GetSettings(); resultMap[iTarget] = targetSettings; success = false; } } if (!success) { status = HttpStatusCode.InternalServerError; } } readySignal.Set(); }); // lastly create an update for all clients if (!readySignal.WaitOne(10000)) { return(HttpStatusCode.InternalServerError); } if (status != HttpStatusCode.OK) { return(status); } //var responseSubject = new JsonString(subject); { var updateData = JsonString.CreateArray(); { for (int i = sensorIndex; i <= sensorIndex; i++) { var entry = JsonString.CreateDict(); EquipmentSettings settings; if (resultMap.TryGetValue(i, out settings)) { entry.AddTerminal("inuse", "true"); entry.AddJsonString("settings", EquipmentSettings.ToJson(settings)); } else { entry.AddTerminal("inuse", "false"); } updateData.AddJsonString(string.Empty, entry); } } responseSubject.AddJsonString("data", updateData); } return(HttpStatusCode.OK); }
public override HttpStatusCode Respond(JsonString subject, JsonString response) { if (subject == null) { throw new ArgumentNullException("subject"); } if (response == null) { throw new ArgumentNullException("response"); } // read properties from the request string topic = JsonString.ParseString(subject.GetTerminal("topic", string.Empty), string.Empty); if (!topic.Equals("sensorCapture")) { return(HttpStatusCode.BadRequest); } int positionStart, positionEnd; if (!ReadPosition(subject, out positionStart, out positionEnd)) { return(HttpStatusCode.BadRequest); } if (positionStart != positionEnd) { // not supported return(HttpStatusCode.BadRequest); } var template = new JsonString(response); template.RemoveTerminal("requestId"); var responseSubject = JsonString.CreateDict(); { responseSubject.AddTerminal("type", "\"post\""); responseSubject.AddTerminal("topic", "\"sensorCapture\""); responseSubject.AddTerminal("position", JsonString.Stringify(positionStart)); responseSubject.AddJsonString("data", JsonString.CreateArray()); } response.AddJsonString("subject", responseSubject); // the client can request optional information // captured images can take a lot of bandwidth and are there off by default int timeout = 10000; bool includeImage = false; var dataArray = subject.GetJsonString("data"); if (dataArray != null) { var data = dataArray.GetJsonString(0); if (data != null) { timeout = JsonString.ParseInt(data.GetTerminal("timeout", ""), (int)timeout); includeImage = JsonString.ParseBool(data.GetTerminal("includeImage", "false"), false); } } // try to get sensor data // here we create an observer-relay pair that relays captured data to explicitly requesting clients // a request will be active for a couple of seconds, then the client has to resend it // the sensor observer generates data when the webcam is active // which is send to the client through LiveWire subscription (relay) // TODO advance this functionality // TODO distinguish between different types of requests (start/stop/only for live stats e.g. fps/+image data) // TODO need a lock here too? int iSensor = positionStart; var readySignal = new AutoResetEvent(false); object sync = new object(); ulong relayID = LiveCaptureSubscription.GenerateSubscriptionID(clientOrigin, SensorType.Webcam, iSensor); LiveCaptureSubscription relay = new LiveCaptureSubscription(relayID); HttpStatusCode status = HttpStatusCode.InternalServerError; CaptureSystem.Instance.Invoke((object sender, EventArgs args) => { var system = (CaptureSystem)sender; // make sure the sensor is started // and subscribe to it if successful ISensorBase sensor = system.GetSensor(iSensor); if (sensor == null || sensor.SensorType != SensorType.Webcam) { lock (sync) { status = HttpStatusCode.NotFound; } readySignal.Set(); return; } lock (sync) { // when the observer times out its subscription to camera events should end // in order to save resources // the observer cancels the relay in the process var observer = new WebcamCaptureObserver(timeout, includeImage, clientOrigin, relay, iSensor, template); IDisposable subscription = system.ObserveSensor(positionStart).Subscribe(observer); observer.Cancelled += delegate { subscription.Dispose(); }; LogManager.Instance.LogMessage(this, string.Format("Subscribed client {0} to webcam {1} as {2}", clientOrigin, iSensor, relayID)); status = HttpStatusCode.OK; } readySignal.Set(); }); // cancellation makes sure that a client is only fed by one observer-relay pair at a time // search for conflicting subscriptions and cancel them // conflicts have the same ID as generated above var activeConsumers = server.GetSubscriptions(clientOrigin); foreach (var c in activeConsumers) { if (c.SubscriptionID == relayID) { c.Cancel(); LogManager.Instance.LogMessage(this, string.Format("Replaced webcam video subscription {0} for client {1}", relayID, clientOrigin)); } } // wait for the external operation above to finish // starting a webcam can take a few seconds if (!readySignal.WaitOne(10000)) { relay.Dispose(); return(HttpStatusCode.InternalServerError); } // since we have no synchronization other than on readySignal we make use of an additional lock // otherwise the ready signal could be set, while we see an old status code value // TODO check validity of statement above lock (sync) { if (status != HttpStatusCode.OK) { relay.Dispose(); return(status); } if (!server.Subscribe(clientOrigin, relay)) { relay.Dispose(); return(HttpStatusCode.InternalServerError); } return(HttpStatusCode.OK); } // TODO create an update in case the sensor was started }