private static void OnPacketReceived(object sender, IList <byte> data) { DateTime receivedTime = DateTime.Now; try { var packet = PacketDecoder.DecodeBytes(data as byte[] ?? data.ToArray()); if (packet == null) { var localBytes = data.ToArray(); Task.Run(() => _dataStore?.RecordUndecipherable(localBytes)); Task.Run(() => { OutputWriter.Write(receivedTime.ToString()); OutputWriter.Write(" Unhandled Packet: "); OutputWriter.WriteLine(OutputWriter.Encoding.GetString(localBytes)); }); return; } //Do this in a Task to avoid waiting if we've scrolled up. var consoleTask = Task.Run(() => OutputWriter.WriteLine($"Packet {receivedTime}: {packet}")); switch (packet.type) { case PacketTypes.Weather: foreach (var serverPoster in _serverPosters) { serverPoster?.SendWeatherDataAsync(packet, receivedTime); } break; case PacketTypes.Response: case PacketTypes.Command: case PacketTypes.Ping: case PacketTypes.Modem: break; default: //nps is often stdOut in debugging, don't write to it from multiple threads: var localBytes = data.ToArray(); consoleTask.ContinueWith(notUsed => { OutputWriter?.Write($"{DateTime.Now} Unhandled Packet: "); OutputWriter?.WriteLine(Encoding.ASCII.GetString(localBytes)); }); break; } Task.Run(() => _dataStore?.RecordPacket(packet)); } catch (Exception ex) { ErrorWriter.WriteLine($"Error {DateTime.Now}: {ex}"); } }
private void InitMultiple(IEnumerable <byte> stationIDs, bool demandRelay) { ConcurrentDictionary <byte, BasicResponse> responses = new ConcurrentDictionary <byte, BasicResponse>(); Dictionary <byte, AutoResetEvent> acksReceived = stationIDs .ToDictionary(id => id, id => new AutoResetEvent(false)); ConcurrentDictionary <byte, byte> unIds = new ConcurrentDictionary <byte, byte>(); void packetReceived(object sender, IList <byte> data) { try { var packet = PacketDecoder.DecodeBytes(data.ToArray()); var packetSrc = packet.sendingStation; if (packet.type == PacketTypes.Response && stationIDs.Any(id => id == packetSrc) && unIds.TryGetValue(packetSrc, out var statUnId) && statUnId == packet.uniqueID) { responses[packetSrc] = (BasicResponse)packet.packetData; acksReceived[packetSrc].Set(); } } catch { } } _communicator.PacketReceived += packetReceived; try { foreach (var id in stationIDs) { unIds[id] = InitUploadToStation(id, demandRelay); } OutWriter?.WriteLine("Waiting for acknowledgements..."); if (!WaitHandle.WaitAll(acksReceived.Values.ToArray(), ResponseTimeout)) { throw new ProgrammerException($"No response received from programming init message. " + $"Failed: {acksReceived.Where(kvp => kvp.Value.WaitOne(0) == false).Select(kvp => kvp.Key).ToCsv()}"); } if (responses.Values.Any(r => r != BasicResponse.OK)) { throw new ProgrammerException($"Non-OK response received from programming init message for stations " + $"({responses.Where(kvp => kvp.Value != BasicResponse.OK).Select(kvp => kvp.Key).ToCsv()})"); } } finally { _communicator.PacketReceived -= packetReceived; } }
public Task <List <byte> > ReadRemoteImageAsync(byte stationID, CancellationToken token) { int imageOffset = 10; const int packetSize = 192; StringBuilder s = new StringBuilder(); byte lastUniqueID = 0; byte[] lastData = null; var replyReceived = new AutoResetEvent(false); return(Task.Run(() => { void packetReceived(object sender, IList <byte> bytes) { var packet = PacketDecoder.DecodeBytes(bytes.ToArray()); if (packet?.type == PacketTypes.Response && packet.uniqueID == lastUniqueID && packet.sendingStation == stationID) { lastData = (byte[])packet.packetData; replyReceived.Set(); } } _communicator.PacketReceived += packetReceived; try { var ret = new List <byte>(_image.Count); for (int i = 0; i < _image.Count; i += packetSize) { int payloadSize = Math.Min(_image.Count - i, packetSize); do { token.ThrowIfCancellationRequested(); lastUniqueID = QueryStationFlash(stationID, (ushort)(i + imageOffset), (byte)payloadSize); }while (WaitHandle.WaitAny(new WaitHandle[] { replyReceived, token.WaitHandle }, ResponseTimeout) == WaitHandle.WaitTimeout || lastData == null); Debug.Assert(lastData.Length == payloadSize); ret.AddRange(lastData); } Debug.Assert(ret.Count == _image.Count); return ret; } finally { _communicator.PacketReceived -= packetReceived; } }, token)); }
/// <summary> /// Finds out which packets a station still needs and sends them until it's got everything. /// </summary> /// <param name="destinationStationID">The station to upload to. /// This cannot be zero - it must be a specific station</param> /// <param name="token"></param> /// <returns></returns> public Task CompleteUploadToStationAsync(byte destinationStationID, CancellationToken token) { if (destinationStationID == 0) { throw new ArgumentOutOfRangeException(nameof(destinationStationID), "destinationStationID cannot be zero for complete upload."); } return(Task.Run(() => { AutoResetEvent replyReceived = new AutoResetEvent(false); byte lastUniqueID = 0; ProgrammingResponse lastResponse = null; void packetReceived(object sender, IList <byte> data) { try { var packet = PacketDecoder.DecodeBytes(data.ToArray()); if (packet?.type == PacketTypes.Response && packet.uniqueID == lastUniqueID && packet.sendingStation == destinationStationID) { lastResponse = packet.packetData as ProgrammingResponse; replyReceived.Set(); } } catch { } } _communicator.PacketReceived += packetReceived; try { while (true) { token.ThrowIfCancellationRequested(); // Get the station status: OutWriter.WriteLine($"Programmer: Query status of {destinationStationID}"); lastUniqueID = QueryStationProgramming(destinationStationID); if (WaitHandle.WaitAny(new WaitHandle[] { replyReceived, token.WaitHandle }, ResponseTimeout) == WaitHandle.WaitTimeout || lastResponse == null) { continue; } // Check that the station is expecting us: if (lastResponse.expectedCRC != CRC) { throw new ProgrammerException($"Station/Programmer CRC mismatch. Station: {lastResponse.expectedCRC:X}, Programmer: {CRC:X}"); } if (lastResponse.totalExpectedPackets != PacketCount) { throw new ProgrammerException($"Station/Programmer packet count mismatch. Station: {lastResponse.totalExpectedPackets}, Programmer: {PacketCount}"); } // Check if it's all done if (lastResponse.allThere) { if (!lastResponse.crcMatch) { throw new ProgrammerException($"Station total CRC mistmatch."); //Nothing we can do at this point. Gotta fail. } else { return; //All there and CRC matches. } } if (lastResponse.receivedPackets.All(a => a)) { throw new ProgrammerException("Packet doesn't report all there, but reports all packets received."); } // Send what's not done: for (int i = 0; i < PacketCount; i++) { token.ThrowIfCancellationRequested(); if (lastResponse.receivedPackets[i]) { continue; } SendImagePacket(destinationStationID, (byte)'C', i); Thread.Sleep(PacketInterval); } } } finally { _communicator.PacketReceived -= packetReceived; } }, token)); }