public void StatusPacketReceived(StatusPacket statusPacket) { Console.WriteLine("ROUTER: #" + statusPacket.deviceId + " (" + statusPacket.shortAddress + " = #" + Device.RouterAltId(statusPacket.shortAddress) + "), parent " + statusPacket.parentAddress + " (" + statusPacket.parentAltAddress + " = #" + Device.RouterAltId(statusPacket.parentAltAddress) + ")."); Console.Write("NEIGHBOURS of #" + Device.RouterAltId(statusPacket.shortAddress) + ": "); for (int i = 0; i < statusPacket.neighbours.Length; i++) { Console.Write("#" + statusPacket.neighbours[i] + "; "); } Console.WriteLine(""); Device device = null; if (devices.ContainsKey(statusPacket.deviceId)) { device = devices[statusPacket.deviceId]; } else { Console.WriteLine("NOTICE: New router: " + statusPacket.deviceId + ""); device = new Device(statusPacket.deviceId, false); devices.Add(statusPacket.deviceId, device); } device.AddStatus(statusPacket); //throw new NotImplementedException(); }
protected void UpdateModel() { if (manager != null) { // Ensure we can access the collection without interruption lock (manager) { // Build a map of router short addresses IDictionary <ushort, ushort> shortAddressMap = new Dictionary <ushort, ushort>(); foreach (Device device in manager.Devices.Values) { if (device.ShortAddress != 0xffff) { ushort altId = (ushort)Device.RouterAltId(device.ShortAddress); ushort id = (ushort)device.Id; if (!shortAddressMap.ContainsKey(altId)) { shortAddressMap.Add(altId, id); } } } // Update sensors foreach (Sensor sensor in sensors.Values) { if (manager.Devices.ContainsKey(sensor.Id)) { Device device = manager.Devices[sensor.Id]; sensor.Age = device.DataAge; sensor.ParentAddress = device.ParentAddress; RenewConnection((ushort)sensor.Id, sensor.ParentAddress, true, sensor.Age); } } // Update routers foreach (Router router in routers.Values) { if (manager.Devices.ContainsKey(router.Id)) { Device device = manager.Devices[router.Id]; router.Age = device.DataAge; router.ParentAddress = device.ParentAddress; // Map short addresses to actual addresses List <ushort> neighbourList = new List <ushort>(); foreach (ushort neighbourShortAddress in device.NeighbourShortAddresses) { if (shortAddressMap.ContainsKey(neighbourShortAddress)) { neighbourList.Add(shortAddressMap[neighbourShortAddress]); //Console.WriteLine("NOTE: Alt. address for neighbour of device " + device.Id + ": #" + neighbourShortAddress + ""); } else { // Console.WriteLine("NOTE: Unknown alt. address for neighbour of device " + device.Id + ": #" + neighbourShortAddress + ""); } } ushort[] neighbours = neighbourList.ToArray(); router.Neighbours = neighbours; // Update connections RenewConnection((ushort)router.Id, router.ParentAddress, true, router.Age); foreach (ushort neighbour in neighbours) { RenewConnection((ushort)router.Id, neighbour, false, router.Age); } } } // Remove dead connections foreach (KeyValuePair <int, List <Connection> > pair in connections) { List <Connection> toDelete = new List <Connection>(); foreach (Connection connection in pair.Value) { if (connection.DataAge > MAX_CONNECTION_AGE) { toDelete.Add(connection); } } foreach (Connection connection in toDelete) { Console.WriteLine("CONNECTION: Removed " + connection.A + " -> " + connection.B + " (" + connection.Parent + ") (t=" + connection.DataAge + ")."); pair.Value.Remove(connection); } } } } }
// 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); }