Beispiel #1
0
 public SensorDataPacket(ISensorBase sensor, SensorDataType type, object data, long packetID)
 {
     Sensor      = sensor;
     DataType    = type;
     GenericData = data;
     PacketID    = packetID;
 }
Beispiel #2
0
 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);
     }
 }
Beispiel #3
0
 /// <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);
         }
     }
 }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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
        }
Beispiel #8
0
 public void OnStopped(ISensorBase sensor)
 {
     // not exepcted
     OnCancel();
 }
Beispiel #9
0
 public void OnStarted(ISensorBase sensor)
 {
     HandleTimeout();
 }
Beispiel #10
0
 public void OnDisconnected(ISensorBase sensor)
 {
     // something went wrong
     OnCancel();
 }
Beispiel #11
0
 public void OnConnected(ISensorBase sensor)
 {
     HandleTimeout();
 }