public void Playback()
        {
            Stream networkStream = null;

            try
            {
                networkStream = ConnectToImageServer();
                // Errors are handled by ConnectToImageServer
                if (networkStream == null)
                {
                    return;
                }

                _playback = true;
                int maxbuf = 1024 * 64;

                string sendBuffer = FormatConnect();

                // Deliberately not encoded as UTF-8
                // With XPCO and XPE/WinAuth only the camera GUID and the token are used. These are always 7 bit ASCII
                // With XPE/BasicAuth, the username and password are in clear text. The server expect bytes in it's own current code page.
                // Encoding this as UTF-8 will prevent corrent authentication with other than 7-bit ASCII characters in username and password
                // Encoding this with "Default" will at least make other than 7-bit ASCII work when client's and server's code pages are alike
                // XPE's Image Server Manager has an option of manually selecting a code page.
                // But there is no way in which a client can obtain the XPE server's code page selection.
                Byte[] bytesSent = Encoding.Default.GetBytes(sendBuffer);
                networkStream.Write(bytesSent, 0, bytesSent.Length);

                Byte[] bytesReceived = new Byte[maxbuf];

                int    bytes = RecvUntil(networkStream, bytesReceived, 0, maxbuf);
                string page  = Encoding.UTF8.GetString(bytesReceived, 0, bytes);

                PlaybackSendConnectUpdateFlag = false; // We just got a new token, old renewal requests can be ignored.

                bool        authenticated = false;
                XmlDocument doc           = new XmlDocument();
                doc.LoadXml(page);
                XmlNodeList nodes = doc.GetElementsByTagName("connected");
                foreach (XmlNode node in nodes)
                {
                    if (node.InnerText.ToLower() == "yes")
                    {
                        authenticated = true;
                    }
                }

                if (!authenticated)
                {
                    // Tell the application I'm done
                    if (OnConnectionStoppedMethod != null)
                    {
                        Control pj = (Control)_renderObject;
                        pj.Dispatcher.Invoke(OnConnectionStoppedMethod,
                                             new Object[] { new ConnInfo(IscErrorCode.InvalidCredentials, "") });
                    }

                    return;
                }

                int  count = 1;
                bool atEnd = false;
                _playbackTime = PlaybackStartTime;
                while (_playback && !atEnd)
                {
                    if (_playbackSendConnectUpdateFlag)
                    {
                        _playbackSendConnectUpdateFlag = false;
                        sendBuffer = FormatConnectUpdate();
                        bytesSent  = Encoding.UTF8.GetBytes(sendBuffer);
                        networkStream.Write(bytesSent, 0, bytesSent.Length);

                        bytes = RecvUntil(networkStream, bytesReceived, 0, maxbuf);
                    }

                    int curBufSize = maxbuf;

                    int qual = _quality;
                    if (_quality < 1 || _quality > 104)
                    {
                        qual = 100;
                    }

                    sendBuffer = string.Format(
                        "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodcall><requestid>{0}</requestid>" +
                        "<methodname>goto</methodname>" +
                        "<time>{1}</time>" +
                        "<compressionrate>{2}</compressionrate>" +
                        "<keyframesonly>no</keyframesonly>" +
                        "</methodcall>\r\n\r\n",
                        ++count, _playbackTime, qual);

                    bytesSent = Encoding.UTF8.GetBytes(sendBuffer);
                    networkStream.Write(bytesSent, 0, bytesSent.Length);

                    bytes = RecvUntil(networkStream, bytesReceived, 0, maxbuf);
                    if (bytes < 0)
                    {
                        throw new Exception("Receive error A");
                    }

                    page = Encoding.UTF8.GetString(bytesReceived, 0, bytes);

                    if (bytesReceived[0] == '<')
                    {
                        // This is XML status message
                        continue;
                    }

                    if (bytesReceived[0] == 'I')
                    {
                        // Image
                        ImageInfo h   = ParseHeader(bytesReceived, 0, bytes);
                        DateTime  cur = TimeConverter.From(h.Current);

                        // Taste two first bytes
                        bytes = RecvFixed(networkStream, bytesReceived, 0, 2);
                        bytes = Math.Abs(bytes);
                        if (bytes != 2)
                        {
                            throw new Exception("Receive error 2");
                        }

                        // if (h.Type.Contains("image/jpeg")) // No, XPCO 3.0a can send jpeg with genericbytedata headers
                        if (bytesReceived[0] == 0xFF && bytesReceived[1] == 0xD8)
                        {
                            int neededBufSize = h.Length + 4; //Adding 4 because there is "\r\n\r\n" at the end
                            if (neededBufSize > curBufSize)
                            {
                                int newBufSize = RoundUpBufSize(neededBufSize);
                                curBufSize = newBufSize;
                                byte b0 = bytesReceived[0];
                                byte b1 = bytesReceived[1];
                                bytesReceived    = new byte[curBufSize];
                                bytesReceived[0] = b0;
                                bytesReceived[1] = b1;
                            }

                            bytes = RecvFixed(networkStream, bytesReceived, 2, neededBufSize - 2);
                            bytes = Math.Abs(bytes);
                            if (bytes != neededBufSize - 2)
                            {
                                throw new Exception("Receive error B");
                            }
                        }
                        else
                        {
                            bytes = RecvFixed(networkStream, bytesReceived, 2, 30);
                            if (Math.Abs(bytes) != 30)
                            {
                                throw new Exception("Receive error C");
                            }

                            short dataType         = BitConverter.ToInt16(GetReversedSubarray(bytesReceived, 0, 2), 0);
                            int   length           = BitConverter.ToInt32(GetReversedSubarray(bytesReceived, 2, 4), 0);
                            short codec            = BitConverter.ToInt16(GetReversedSubarray(bytesReceived, 6, 2), 0);
                            short seqNo            = BitConverter.ToInt16(GetReversedSubarray(bytesReceived, 8, 2), 0);
                            short flags            = BitConverter.ToInt16(GetReversedSubarray(bytesReceived, 10, 2), 0);
                            long  timeStampSync    = BitConverter.ToInt64(GetReversedSubarray(bytesReceived, 12, 8), 0);
                            long  timeStampPicture = BitConverter.ToInt64(GetReversedSubarray(bytesReceived, 20, 8), 0);
                            int   reserved         = BitConverter.ToInt32(GetReversedSubarray(bytesReceived, 28, 4), 0);

                            bool isKeyFrame    = (flags & 0x01) == 0x01;
                            int  payloadLength = length - 32;

                            if (payloadLength > curBufSize)
                            {
                                int newBufSize = RoundUpBufSize(payloadLength);
                                curBufSize    = newBufSize;
                                bytesReceived = new byte[curBufSize];
                            }

                            //this appears to be the correct amount of data
                            bytes = RecvFixed(networkStream, bytesReceived, 0, payloadLength);
                            bytes = Math.Abs(bytes);
                            if (bytes != payloadLength)
                            {
                                throw new Exception("Receive error D");
                            }
                        }

                        byte[] ms = new byte[bytes];
                        Buffer.BlockCopy(bytesReceived, 0, ms, 0, bytes);
                        h.Data = ms;

                        if (OnImageReceivedMethod != null)
                        {
                            Control pi = (Control)_renderObject;
                            pi.Dispatcher.Invoke(OnImageReceivedMethod, h);
                        }

                        // Stop if we reach the end of the sequence
                        long nextTime = long.Parse(h.Next);
                        if (nextTime > PlaybackEndTime)
                        {
                            break;
                        }

                        // If there is no more video, do not keep repeating the last image, but stop the playback.
                        if (nextTime == _playbackTime)
                        {
                            break;
                        }

                        int interval =
                            (int)(nextTime -
                                  _playbackTime);  // We ought to subtract also the number of milliseconds elapsed in real time since last update
                        _playbackTime = nextTime;

                        Thread.Sleep(interval / _speed);
                    }
                }

                // Tell the application I'm done
                if (OnConnectionStoppedMethod != null)
                {
                    Control pij = (Control)_renderObject;
                    pij.Dispatcher.Invoke(OnConnectionStoppedMethod, new ConnInfo(IscErrorCode.Success, ""));
                }
            }

            catch (OutOfMemoryException)
            {
                Control ipj = (Control)_renderObject;
                ipj.Dispatcher.Invoke(OnConnectionStoppedMethod, new ConnInfo(IscErrorCode.OutOfMemory, ""));
            }
            catch (IOException e)
            {
                string  s   = e.Message;
                Control ipj = (Control)_renderObject;
                ipj.Dispatcher.Invoke(OnConnectionStoppedMethod,
                                      new ConnInfo(IscErrorCode.SocketError, e.Message));
            }
            catch (Exception e)
            {
                Control ipj = (Control)_renderObject;
                ipj.Dispatcher.Invoke(OnConnectionStoppedMethod,
                                      new ConnInfo(IscErrorCode.InternalError, e.Message));
            }
            finally
            {
                networkStream?.Dispose();
            }
        }
        public string GetSequences(DateTime dt, int max)
        {
            Stream networkStream = null;

            try
            {
                networkStream = ConnectToImageServer();
                // Errors are handled by ConnectToImageServer
                if (networkStream == null)
                {
                    return("#No response");
                }

                int maxBuf = 512 * max;

                string sendBuffer = FormatConnect();

                // Deliberately not encoded as UTF-8
                // With XPCO and XPE/WinAuth only the camera GUID and the token are used. These are always 7 bit ASCII
                // With XPE/BasicAuth, the username and password are in clear text. The server expect bytes in it's own current code page.
                // Encoding this as UTF-8 will prevent corrent authentication with other than 7-bit ASCII characters in username and password
                // Encoding this with "Default" will at least make other than 7-bit ASCII work when client's and server's code pages are alike
                // XPE's Image Server Manager has an option of manually selecting a code page.
                // But there is no way in which a client can obtain the XPE server's code page selection.
                Byte[] bytesSent = Encoding.Default.GetBytes(sendBuffer);
                networkStream.Write(bytesSent, 0, bytesSent.Length);

                Byte[] bytesReceived = new Byte[maxBuf];
                int    bytes         = RecvUntil(networkStream, bytesReceived, 0, maxBuf);
                string page          = Encoding.UTF8.GetString(bytesReceived, 0, bytes);

                bool        authenticated = false;
                XmlDocument doc           = new XmlDocument();
                doc.LoadXml(page);
                XmlNodeList nodes = doc.GetElementsByTagName("connected");
                foreach (XmlNode node in nodes)
                {
                    if (node.InnerText.ToLower() == "yes")
                    {
                        authenticated = true;
                    }
                }


                if (!authenticated)
                {
                    XmlNodeList errorNodes = doc.GetElementsByTagName("errorreason");
                    String      tx         = "";
                    if (errorNodes != null && errorNodes.Count > 0)
                    {
                        tx = errorNodes[0].InnerText;
                    }

                    return("#" + tx);
                }

                double centerTime = Math.Round(TimeConverter.ToDouble(dt));
                double startTime  = Math.Round(TimeConverter.ToDouble(dt - TimeSpan.FromHours(24)));
                double timespan   = Math.Round(centerTime - startTime);
                sendBuffer = string.Format(
                    "<?xml version=\"1.0\" encoding=\"utf-8\"?><methodcall><requestid>1</requestid>" +
                    "<methodname>alarms</methodname>" +
                    "<centertime>{0}</centertime>" +
                    "<timespan>{1}</timespan>" +
                    "<numalarms>{2}</numalarms>" +
                    "</methodcall>\r\n\r\n", centerTime.ToString(), timespan.ToString(), max);

                bytesSent = Encoding.UTF8.GetBytes(sendBuffer);
                networkStream.Write(bytesSent, 0, bytesSent.Length);

                bytes = RecvUntil(networkStream, bytesReceived, 0, maxBuf);
                if (bytes < 0)
                {
                    bytes = -bytes;
                }
                page = Encoding.UTF8.GetString(bytesReceived, 0, bytes);

                return(page);
            }
            catch
            {
                return("");
            }
            finally
            {
                networkStream?.Dispose();
            }
        }
Ejemplo n.º 3
0
        private void _cameraCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (_recvThread != null)
            {
                return;
            }

            VideoImage = null;
            NotifyPropertyChanged("VideoImage");
            PlaybackTimeString = "";
            NotifyPropertyChanged("PlaybackTimeString");

            int i = _cameraCombo.SelectedIndex;

            SystemAccess.Camera   camera = _cameras[i];
            ImageServerConnection isc    = new ImageServerConnection(camera.RecorderUri, camera.Guid.ToString(), 75);

            isc.SetCredentials(_sysInfo);
            string sequences = isc.GetSequences(DateTime.Now, 16);

            _sequenceList.Items.Clear();
            _sequenceStartTimes = new List <long>();
            _sequenceEndTimes   = new List <long>();
            if (sequences.StartsWith("#"))
            {
                _sequenceList.Items.Add(sequences.Substring(1));
                return;
            }

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(sequences);
                XmlNodeList nodes = doc.GetElementsByTagName("alarm");
                foreach (XmlNode node in nodes)
                {
                    XmlAttributeCollection attrs = node.Attributes;
                    string start = "";
                    string end   = "";
                    string alarm = "??";

                    for (int ii = 0; ii < attrs.Count; ii++)
                    {
                        XmlAttribute attr = (XmlAttribute)attrs.Item(ii);
                        if (attr.Name.ToLower().Equals("starttime"))
                        {
                            start = attr.Value;
                        }
                        if (attr.Name.ToLower().Equals("endtime"))
                        {
                            end = attr.Value;
                        }
                        if (attr.Name.ToLower().Equals("alarmtime"))
                        {
                            alarm = attr.Value;
                        }
                    }

                    long     ss  = long.Parse(start);
                    long     ee  = long.Parse(end);
                    DateTime sdt = TimeConverter.From(start);
                    DateTime edt = TimeConverter.From(end);
                    TimeSpan sql = edt - sdt;

                    _sequenceList.Items.Insert(0, sdt.ToLongTimeString() + " (" + sql.Seconds + " s)");
                    _sequenceStartTimes.Insert(0, ss);
                    _sequenceEndTimes.Insert(0, ee);
                }
            }
            catch (Exception ex)
            {
                string s = ex.Message;
            }
        }