public async Task <PodCommandResult> PerformExchange(IMessage requestMessage, IMessageExchangeParameters messageExchangeParameters, IMessageProgress messageProgress, CancellationToken ct) { var previousContext = SynchronizationContext.Current; try { // SynchronizationContext.SetSynchronizationContext(MessageSynchronizationContext); var messageExchange = await MessageExchangeProvider.GetMessageExchanger(messageExchangeParameters, Pod, messageProgress, ct).ConfigureAwait(false); var response = await messageExchange.GetResponse(requestMessage, messageProgress, ct); return(messageExchange.ParseResponse(response, Pod)); } catch (Exception e) { return(new PodCommandResult() { Success = false }); } finally { // SynchronizationContext.SetSynchronizationContext(previousContext); } }
public override async Task CancelBolus(IMessageProgress progress, CancellationToken ct) { try { await UpdateStatusInternal(progress, ct); AssertRunningStatus(); if (BolusState != BolusState.Immediate) { throw new PdmException("Immediate bolus is not running"); } // await send_request(ProtocolHelper.request_cancel_bolus(), true); if (BolusState == BolusState.Immediate) { throw new PdmException("Failed to cancel running bolus"); } } catch (OmniCoreException) { throw; } catch (Exception e) { throw new PdmException("Unexpected error", e); } }
//private async Task send_request(IRequest request, bool with_nonce = false) //{ //if (with_nonce) //{ // var nonce_val = this.Nonce.GetNext(); // request.set_nonce(nonce_val); // nonce_syncword = null; //} //var me = new MessageExchange(request, this.packetRadio, this.Pod); //var response = await me.GetPodResponse(); //ProtocolHelper.response_parse(response, this.Pod); //if (with_nonce && nonce_syncword != null) //{ // Debug.WriteLine("Nonce resync requested"); // this.Nonce.Sync(request.sequence.Value); // var nonce_val = this.Nonce.GetNext(); // request.set_nonce(nonce_val); // nonce_syncword = null; // radio_message_sequence = request.sequence.Value; // response = await me.GetPodResponse(); // ProtocolHelper.response_parse(response, this.Pod); // if (nonce_syncword != null) // { // this.Nonce.Reset(); // throw new PdmException("Nonce sync failed"); // } //} //} private async Task <PodCommandResult> UpdateStatusInternal(IMessageProgress progress, CancellationToken ct, StatusRequestType update_type = StatusRequestType.Standard) { var request = new ErosMessageBuilder().WithStatus(update_type).Build(); return(await MessageHandler.PerformExchange(request, StandardParameters, progress, ct)); }
public async Task InitializeExchange(IMessageProgress messageProgress, CancellationToken ct) { if (FinalAckTask != null) { await FinalAckTask; } await RileyLink.Connect(); }
public override async Task UpdateStatus(IMessageProgress progress, CancellationToken ct, StatusRequestType update_type = StatusRequestType.Standard) { try { Debug.WriteLine($"Updating pod status, request type {update_type}"); await this.UpdateStatusInternal(progress, ct, update_type); } catch (OmniCoreException) { throw; } catch (Exception e) { throw new PdmException("Unexpected error", e); } }
public override async Task AcknowledgeAlerts(IMessageProgress progress, CancellationToken ct, byte alert_mask) { try { Debug.WriteLine($"Acknowledging alerts, bitmask: {alert_mask}"); await UpdateStatusInternal(progress, ct); AssertImmediateBolusInactive(); if (Progress < PodProgress.PairingSuccess) { throw new PdmException("Pod not paired completely yet."); } if (Progress == PodProgress.ErrorShuttingDown) { throw new PdmException("Pod is shutting down, cannot acknowledge alerts."); } if (Progress == PodProgress.AlertExpiredShuttingDown) { throw new PdmException("Acknowledgement period expired, pod is shutting down"); } if (Progress > PodProgress.AlertExpiredShuttingDown) { throw new PdmException("Pod is not active"); } if ((AlertMask & alert_mask) != alert_mask) { throw new PdmException("Bitmask is invalid for current alert state"); } // await send_request(ProtocolHelper.request_acknowledge_alerts(alert_mask)); } catch (OmniCoreException) { throw; } catch (Exception e) { throw new PdmException("Unexpected error", e); } }
public async Task <IMessageExchange> GetMessageExchanger(IMessageExchangeParameters messageExchangeParameters, IPod pod, IMessageProgress messageProgress, CancellationToken ct) { if (RileyLinkInstance == null) { RileyLinkInstance = new RileyLink(); } if (RileyLinkMessageExchange == null) { RileyLinkMessageExchange = new RileyLinkMessageExchange(messageExchangeParameters, pod, RileyLinkInstance); } else { RileyLinkMessageExchange.UpdateParameters(messageExchangeParameters, pod, RileyLinkInstance); } await RileyLinkMessageExchange.InitializeExchange(messageProgress, ct); return(RileyLinkMessageExchange); }
public override async Task Bolus(IMessageProgress progress, CancellationToken ct, decimal bolusAmount) { try { Debug.WriteLine($"Bolusing {bolusAmount}U"); await UpdateStatusInternal(progress, ct); AssertRunningStatus(); AssertImmediateBolusInactive(); if (bolusAmount < 0.05m) { throw new PdmException("Cannot bolus less than 0.05U"); } if (bolusAmount % 0.05m != 0) { throw new PdmException("Bolus must be multiples of 0.05U"); } if (bolusAmount > 30m) { throw new PdmException("Cannot bolus more than 30U"); } // await send_request(ProtocolHelper.request_bolus(bolusAmount), true); if (BolusState != BolusState.Immediate) { throw new PdmException("Pod did not start bolusing"); } } catch (OmniCoreException) { throw; } catch (Exception e) { throw new PdmException("Unexpected error", e); } }
public async Task <IMessage> GetResponse(IMessage requestMessage, IMessageProgress messageExchangeProgress, CancellationToken ct) { this.Started = DateTime.UtcNow; if (MessageExchangeParameters.TransmissionLevelOverride.HasValue) { RileyLink.SetTxLevel(MessageExchangeParameters.TransmissionLevelOverride.Value); } var erosRequestMessage = requestMessage as ErosMessage; var packets = GetRadioPackets(erosRequestMessage); RadioPacket received = null; var packet_count = packets.Count; this.unique_packets = packet_count * 2; for (int part = 0; part < packet_count; part++) { var packet = packets[part]; int repeat_count = -1; int timeout = 10000; while (true) { repeat_count++; if (repeat_count == 0) { Debug.WriteLine($"Sending PDM message part {part + 1}/{packet_count}"); } else { Debug.WriteLine($"Sending PDM message part {part + 1}/{packet_count} (Repeat: {repeat_count})"); } PacketType expected_type; if (part == packet_count - 1) { expected_type = PacketType.POD; } else { expected_type = PacketType.ACK; } try { received = await this.ExchangePackets(packet.with_sequence(this.Pod.PacketSequence), expected_type, timeout); break; } catch (OmniCoreTimeoutException) { Debug.WriteLine("Trying to recover from timeout error"); if (part == 0) { if (repeat_count == 0) { timeout = 15000; continue; } else if (repeat_count == 1) { timeout = 10000; Thread.Sleep(2000); continue; } else if (repeat_count == 2) { await RileyLink.Reset(); timeout = 15000; continue; } else { Debug.WriteLine("Failed recovery"); Pod.PacketSequence = 0; throw; } } else if (part < packet_count - 1) { if (repeat_count < 2) { timeout = 20000; continue; } else { throw; } } else { if (repeat_count < 10) { timeout = 20000; continue; } else { throw; } } } catch (PacketRadioException) { Debug.WriteLine("Trying to recover from radio error"); this.radio_errors++; if (part == 0) { if (repeat_count < 2) { await RileyLink.Reset(); continue; } else if (repeat_count < 4) { await RileyLink.Reset(); timeout = 10000; Thread.Sleep(2000); continue; } else { Debug.WriteLine("Failed recovery"); throw; } } else if (part < packet_count - 1) { if (repeat_count < 6) { await RileyLink.Reset(); timeout = 10000; Thread.Sleep(2000); continue; } else { Debug.WriteLine("Failed recovery"); throw; } } else { if (repeat_count < 10) { await RileyLink.Reset(); timeout = 10000; Thread.Sleep(2000); continue; } else { Debug.WriteLine("Failed recovery"); Pod.PacketSequence = 0; throw; } } } catch (ErosProtocolException pe) { if (pe.ReceivedPacket != null && expected_type == PacketType.POD && pe.ReceivedPacket.type == PacketType.ACK) { Debug.WriteLine("Trying to recover from protocol error"); this.Pod.PacketSequence++; return(await GetResponse(requestMessage, messageExchangeProgress, ct)); } else { throw pe; } } catch (Exception) { throw; } } part++; this.Pod.PacketSequence = (received.sequence + 1) % 32; } Debug.WriteLine($"SENT MSG {requestMessage}"); var part_count = 0; if (received.type == PacketType.POD) { part_count = 1; Debug.WriteLine($"Received POD message part {part_count}"); } var responseBuilder = new ErosResponseBuilder(); var radioAddress = Pod.RadioAddress; if (MessageExchangeParameters.AddressOverride.HasValue) { radioAddress = MessageExchangeParameters.AddressOverride.Value; } var ackAddress = radioAddress; if (MessageExchangeParameters.AckAddressOverride.HasValue) { ackAddress = MessageExchangeParameters.AckAddressOverride.Value; } while (!responseBuilder.WithRadioPacket(received)) { var ackPacket = this.InterimAckPacket(ackAddress, (received.sequence + 1) % 32); received = await this.ExchangePackets(ackPacket, PacketType.CON); part_count++; Debug.WriteLine($"Received POD message part {part_count}"); } var podResponse = responseBuilder.Build(); Debug.WriteLine($"RCVD MSG {podResponse}"); Debug.WriteLine("Send and receive completed."); this.Pod.MessageSequence = (podResponse.sequence.Value + 1) % 16; this.Pod.PacketSequence = (received.sequence + 1) % 32; var finalAckPacket = this.FinalAckPacket(ackAddress, (received.sequence + 1) % 32); FinalAckTask = Task.Run(() => AcknowledgeEndOfMessage(finalAckPacket)); return(podResponse); }
public abstract Task CancelBolus(IMessageProgress progress, CancellationToken ct);
public abstract Task Bolus(IMessageProgress progress, CancellationToken ct, decimal bolusAmount);
public abstract Task AcknowledgeAlerts(IMessageProgress progress, CancellationToken ct, byte alertMask);
public abstract Task UpdateStatus(IMessageProgress progress, CancellationToken ct, StatusRequestType requestType);