예제 #1
0
        // Construct a Packet
        public Packet(DateTime timestamp, ushort deviceId, byte version, ushort battery, ushort adcSample, ushort sequenceId, byte format, ushort sampleCount, DateTime rawTimestamp, int unsent, int temp, int light, int humidity, ushort[] pir, ushort[] audio, Sample[] samples, ushort parentAddress, ushort parentAltAddress)
        {
            Timestamp = timestamp;
            DeviceId = deviceId;
            Version = version;
            Battery = battery;
            AdcSample = adcSample;
            SequenceId = sequenceId;
            Format = format;
            SampleCount = sampleCount;
            RawTimestamp = rawTimestamp;
            Unsent = unsent;
            Temp = temp;
            Light = light;
            Humidity = humidity;
            Pir = pir;
            Audio = audio;

            Samples = samples;

            ParentAddress = parentAddress;
            ParentAltAddress = parentAltAddress;
        }
예제 #2
0
        public void AddSamples(Sample[] samples)
        {
            UpdateTime = DateTime.UtcNow;

            if (samples == null || samples.Length == 0) { return; }

            // If the last index of the new samples is the same as the last index seen -- duplicate packet (ignore)
            if ((int)samples[samples.Length - 1].Index == LastIndex && LastIndex != 0)
            {
                Console.WriteLine("WARNING: Duplicate packet detected (last index: " + LastIndex + ") - ignoring.");
                return;
            }

            // If not a duplicate, and the first index of the new samples is earlier than the last index seen -- must be restart
            if ((int)samples[0].Index < LastIndex && LastIndex != 0)
            {
                // Must have re-started broadcast, clear history
                //if (LastIndex - (int)samples[0].Index > 20)
                Console.WriteLine("WARNING: Restart detected (index: " + samples[0].Index + ", last index: " + LastIndex + ") - clearing history.");
                Clear();
                LastIndex = (int)samples[0].Index - 1;
            }

            // Calculate number of missed packets
            int numMissed = (int)(samples[0].Index - LastIndex - 1);
            if (numMissed < 0) { numMissed = 0; }
            if (numMissed > 1000) { numMissed = 1000; }

            if (numMissed > 0)
            {
                Console.WriteLine("WARNING: Dropped packet(s) detected, missing samples: " + numMissed);
            }

            // Add any missing samples
            Sample[] missedSamples = new Sample[numMissed];
            for (int i = 0; i < missedSamples.Length; i++)
            {
                missedSamples[i] = new Sample((uint)++LastIndex);
            }
            Samples.AddRange(missedSamples);

            // Add samples
            int firstIndex = Samples.Count;
            int length = samples.Length;
            Samples.AddRange(samples);

            // Update last index
            LastIndex = (int)(Samples[Samples.Count - 1].Index);

            // Trim to maximum samples range
            if (Samples.Count > MaxHistory)
            {
                firstIndex -= Samples.Count - MaxHistory;
                if (firstIndex < 0) { length += firstIndex; firstIndex = 0; }
                Samples.RemoveRange(0, Samples.Count - MaxHistory);
            }
        }
예제 #3
0
        /*
        // The time is this time divided by number of ticks per millisecond
        protected static long time() { return DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; }

        public Sample? LastValidSample
        {
            get
            {
                Sample? lastValidSample = null;
                foreach (Sample sample in Samples)
                {
                    if (sample.valid)
                    {
                        lastValidSample = sample;
                    }
                }
                return lastValidSample;
            }
        }

        // Checksum - 16-bit word-size addition
        private static ushort WordSum(byte[] buffer)
        {
            int len = buffer.Length;
            int words = (len / 2);
            ushort value = 0x0000;						        // Initial sum of zero
            for (int i = 0; i < words; i++)
            {
                value += (ushort)(buffer[2 * i] + (buffer[2 * i + 1] << 8));
            }
            if ((len & 1) != 0) { value += buffer[len - 1]; }   // Add odd byte
            return value;
            //return (~value) + 1;								// To calculate the checksum, take bitwise NOT of sum, then add 1 (total sum of words including checksum will be zero)
        }
        */
        public static Packet PacketFromStomp(Hashtable data)
        {
            long timestampReceivedLong = 0;
            long timestampEstimatedLong = 0;
            ushort deviceId = 0;
            byte version = 0;
            ushort battery = 0;
            ushort sequence = 0;
            ushort unsent = 0;
            ushort temp = 0;
            ushort light = 0;
            ushort humidity = 0;
            ushort sampleCount = 0;
            ushort[] pir = new ushort[0];
            ushort[] audio = new ushort[0];
            Sample[] samples = new Sample[0];
            ushort parentAddress = 0xffff;
            ushort parentAltAddress = 0xffff;

            // Check for "TEDDI" packet type, or no type info (old packets),
            if (data != null && (!data.ContainsKey("Type") || data["Type"].ToString() == "TEDDI"))
            {
                if (data.ContainsKey("TimestampEstimated")) { timestampEstimatedLong = (long)(double)Double.Parse(data["TimestampEstimated"].ToString()); }
                if (data.ContainsKey("TimestampReceived")) { timestampReceivedLong = (long)(double)Double.Parse(data["TimestampReceived"].ToString()); }
                if (data.ContainsKey("DeviceId")) { deviceId = (ushort)(double)Double.Parse(data["DeviceId"].ToString()); }
                if (data.ContainsKey("Version")) { version = (byte)(double)Double.Parse(data["Version"].ToString()); }
                if (data.ContainsKey("SampleCount")) { sampleCount = (ushort)(double)Double.Parse(data["SampleCount"].ToString()); }
                if (data.ContainsKey("Sequence")) { sequence = (ushort)(double)Double.Parse(data["Sequence"].ToString()); }
                if (data.ContainsKey("Unsent")) { unsent = (ushort)(double)Double.Parse(data["Unsent"].ToString()); }

                if (data.ContainsKey("Temp")) { temp = (ushort)(double)Double.Parse(data["Temp"].ToString()); }
                if (data.ContainsKey("Light")) { light = (ushort)(double)Double.Parse(data["Light"].ToString()); }
                if (data.ContainsKey("Battery")) { battery = (ushort)(double)Double.Parse(data["Battery"].ToString()); }
                if (data.ContainsKey("Humidity")) { humidity = (ushort)(double)Double.Parse(data["Humidity"].ToString()); }

                if (data.ContainsKey("Samples") && data["Samples"] is ArrayList)
                {
                    ArrayList sampleList = (ArrayList)data["Samples"];
                    samples = new Sample[sampleList.Count];
                    pir = new ushort[sampleList.Count];
                    audio = new ushort[sampleList.Count];
                    for (int i = 0; i < sampleList.Count; i++)
                    {
                        if (sampleList[i] is ArrayList && ((ArrayList)sampleList[i]).Count >= 3)
                        {
                            ArrayList al = (ArrayList)sampleList[i];

                            long ts = 0;
                            uint idx = 0;
                            pir[i] = 0;
                            audio[i] = 0;

                            ts = (long)(double)al[0];
                            idx = (uint)(sequence * sampleCount + i);
                            pir[i]= (ushort)(double)al[1];
                            audio[i] = (ushort)(double)al[2];

                            samples[i] = new Sample(DateTime.FromBinary(ts), (uint)idx, (short)pir[i], (short)temp, (short)light, (short)humidity, (ushort)audio[i], battery);

                        }
                    }
                }

                if (data.ContainsKey("ParentAddress")) { parentAddress = (ushort)(double)Double.Parse(data["ParentAddress"].ToString()); }
                if (data.ContainsKey("ParentAltAddress")) { parentAltAddress = (ushort)(double)Double.Parse(data["ParentAltAddress"].ToString()); }

            }
            else
            {
                Console.Error.Write("[STOMP:null]");
            }

            return new Packet(DateTime.FromBinary(timestampEstimatedLong), deviceId, version, battery, 0, sequence, 0, sampleCount, DateTime.FromBinary(timestampReceivedLong), unsent, temp, light, humidity, pir, audio, samples, parentAddress, parentAltAddress);
        }
예제 #4
0
        // Method to return a Packet, or null if invalid byte array
        public static Packet PacketFromBinary(byte[] buffer, DateTime timestamp)
        {
            Packet packet = null;

            if (buffer != null && buffer.Length > 0)
            {
                if (buffer.Length >= 5 && buffer[0] == 0x12 && buffer[1] == 0x54)           // USER_REPORT_TYPE && TEDDI (ASCII 'T')
                {
                    /*
                    unsigned char  reportType;			// @0  [1] = 0x12 (USER_REPORT_TYPE)
                    unsigned char  reportId;		    // @1  [1] = 0x54 (ASCII 'T')
                    unsigned short deviceId;			// @2  [2] = Short device identifier (16-bit) [doesn't have to be part of the payload, but this format is the same as the WAX]
                    unsigned char version;				// @4  [1] = (0x02 = format [seq/temp/ldr/audio/pir : short])
                    */
                    ushort deviceId = (ushort)(buffer[2] | (((ushort)buffer[3]) << 8));
                    byte version = buffer[4];

                    if (((version & 0x0f) == 0x03 || (version & 0x0f) >= 0x04) && buffer.Length >= 18)
                    {
                        /*
                        unsigned char  reportType;          // @ 0  [1] USER_REPORT_TYPE (0x12)
                        unsigned char  reportId;            // @ 1  [1] Report identifier (0x54, ASCII 'T')
                        unsigned short deviceId;            // @ 2  [2] Device identifier (16-bit)
                        unsigned char  version;             // @ 4  [1] Low nibble = packet version (0x3), high nibble = config (0x0)
                        unsigned char  sampleCount;         // @ 5  [1] Sample count (default config is at 250 msec interval with an equal number of PIR and audio samples; 20 = 5 seconds)
                        unsigned short sequence;            // @ 6  [2] Sequence number (16-bit)
                        unsigned short unsent;              // @ 8  [2] Number of unsent samples (default config is in 250 msec units)
                        unsigned short temp;                // @10  [2] Temperature (0.2 Hz)
                        unsigned short light;               // @12  [2] Light (0.2 Hz)
                        unsigned short battery;             // @14  [2] Battery (0.2 Hz)
                        unsigned short humidity;            // @16  [2] Humidity [V4] (0.2 Hz) -- or [V3] 16-bit checksum to make packet zero-sum
                        unsigned char  data[BITPACK10_SIZEOF(DATA_MAX_INTERVAL * 2)];   // @18 [50] PIR and audio energy (4 Hz, 20x 2x 10-bit samples)
                        unsigned short parentAddress;		// @ADDITIONAL_OFFSET+0  [2] (optional) Parent address
                        unsigned short parentAltAddress;	// @ADDITIONAL_OFFSET+2  [2] (optional) Parent alt. address
                        */
                        byte config = (byte)(buffer[4] >> 4);
                        byte sampleCount = (byte)(buffer[5]);
                        ushort sequence = (ushort)(buffer[6] | (((ushort)buffer[7]) << 8));
                        ushort unsent = (ushort)(buffer[8] | (((ushort)buffer[9]) << 8));
                        ushort temp = (ushort)(buffer[10] | (((ushort)buffer[11]) << 8));
                        ushort light = (ushort)(buffer[12] | (((ushort)buffer[13]) << 8));
                        ushort battery = (ushort)(buffer[14] | (((ushort)buffer[15]) << 8));
                        ushort humidity = (ushort)(buffer[16] | (((ushort)buffer[17]) << 8));
                        ushort[] pir = new ushort[sampleCount];
                        ushort[] audio = new ushort[sampleCount];
                        ushort parentAddress = 0xffff;
                        ushort parentAltAddress = 0xffff;

                        if ((version & 0x0f) == 0x03)
                        {
                            humidity = 0;
                        }

                        int[] teddiFrequency = new int[] { 4, 8, 16, 32, 64, 128, 256, 512, 1, 1,  1,  1,  1,  1,  1,  2 };
                        ushort sampleInterval = (ushort)(1000 / teddiFrequency[config]);

                        try
                        {
                            // Unpack PIR
                            for (int i = 0; i < sampleCount; i++)
                            {
                                pir[i] = BitUnpack_uint10(buffer, i, 18);
                            }

                            // Unpack Audio
                            for (int i = 0; i < sampleCount; i++)
                            {
                                audio[i] = BitUnpack_uint10(buffer, sampleCount + i, 18);
                            }

                            // For V3 data, divide temp/light/battery measurement down
                            if ((version & 0x0f) <= 0x03 && sampleCount > 0)
                            {
                                temp /= sampleCount;
                                light /= sampleCount;
                                battery /= sampleCount;
                                humidity /= sampleCount;
                            }

                            // Check for additional data
                            int additionalIndex = 18 + BITPACK10_SIZEOF(sampleCount * 2);
                            if (additionalIndex + 4 <= buffer.Length)
                            {
                                parentAddress = (ushort)(buffer[additionalIndex + 0] | (((ushort)buffer[additionalIndex + 1]) << 8));
                                parentAltAddress = (ushort)(buffer[additionalIndex + 2] | (((ushort)buffer[additionalIndex + 3]) << 8));
                                Console.WriteLine("SENSOR: #" + deviceId + ", parent " + parentAddress + " (" + parentAltAddress + " = #" + Device.RouterAltId(parentAltAddress) + ").");
                            }

                            // Create samples from the measurement data: deviceId, temp, light, humidity, pir[], audio[]
                            Sample[] sampleData = new Sample[sampleCount];
                            for (uint i = 0; i < sampleCount; i++)
                            {
                                sampleData[i] = new Sample(timestamp - TimeSpan.FromMilliseconds((unsent + sampleCount - 1 - i) * sampleInterval), (ushort)(sequence * sampleCount) + i, (short)pir[i], (short)temp, (short)light, (short)humidity, audio[i], battery);
                            }
                            packet = new Packet(timestamp - TimeSpan.FromMilliseconds((unsent + sampleCount - 1) * sampleInterval), deviceId, 1, 0, 0, (ushort)(sequence * sampleCount), 0, sampleCount, timestamp, unsent, temp, light, humidity, pir, audio, sampleData, parentAddress, parentAltAddress);
                        }
                        catch (IndexOutOfRangeException ex)
                        {
                            Console.Error.Write("EXCEPTION: " + ex + " while parsing packet.");
                        }
                    }
                    else
                    {
                        Console.Error.Write("[T?]");	// Unknown TEDDI packet type
                    }
                }
                else
                {
                    //Console.Error.Write("[?]");		// Unknown packet type
                }
            }
            return packet;
        }