public SensorDataPacket(ISensorBase sensor, SensorDataType type, object data, long packetID) { Sensor = sensor; DataType = type; GenericData = data; PacketID = packetID; }
private void ProcessSensors() { ISensorBase[] toProcess; lock (sensorSync) { if (sensors.Length > 0) { toProcess = new ISensorBase[sensors.Length]; Array.Copy(sensors, toProcess, sensors.Length); } else { return; } } // process all available sensors // and relay captured data for (int i = 0; i < toProcess.Length; i++) { if (toProcess[i] == null || !toProcess[i].Capturing) { continue; } SensorDataPacket packet = toProcess[i].Process(-1); if (packet == null) { continue; } SensorObservable observable; lock (observableSync) { observable = observables[i]; } observable.OnDataAvailable(packet); } }
/// <summary> /// Reports that the sensor has started operating /// and is expected to generate data packets. /// </summary> /// <param name="sensor">Started sensor.</param> public void OnStarted(ISensorBase sensor) { lock (observerSync) { foreach (var observer in observers) { observer.OnStarted(sensor); } } }
public int ConnectSensor(ISensorBase sensor, int preferredIndex = -1) { if (sensor == null) { throw new ArgumentNullException("sensor"); } int iSensor = -1; lock (sensorSync) { // first try to assign the sensor to its preferred index if (preferredIndex >= 0 && preferredIndex < sensors.Length) { if (sensors[preferredIndex] == null) { sensors[preferredIndex] = sensor; iSensor = preferredIndex; } } // if the index is already taken, find the next unassigned index if (iSensor < 0) { for (int i = 0; i < sensors.Length; i++) { if (sensors[i] == null) { sensors[i] = sensor; iSensor = i; break; } } } if (iSensor < 0) { // all indexes assigned, increase storage size return(-1); } } SensorObservable observable; lock (observableSync) { observable = observables[iSensor]; } observable.OnConnected(sensor); return(iSensor); }
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); }
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 }
public void OnStopped(ISensorBase sensor) { // not exepcted OnCancel(); }
public void OnStarted(ISensorBase sensor) { HandleTimeout(); }
public void OnDisconnected(ISensorBase sensor) { // something went wrong OnCancel(); }
public void OnConnected(ISensorBase sensor) { HandleTimeout(); }