MCPcopy Create free account
hub / github.com/Duet3D/RepRapFirmware / SendRequestAndGetCustomReply

Method SendRequestAndGetCustomReply

src/CAN/CanInterface.cpp:793–891  ·  view source on GitHub ↗

Send a request to an expansion board and append the response to 'reply'. The response may either be a standard reply or 'replyType'.

Source from the content-addressed store, hash-verified

791
792// Send a request to an expansion board and append the response to 'reply'. The response may either be a standard reply or 'replyType'.
793GCodeResult CanInterface::SendRequestAndGetCustomReply(CanMessageBuffer *buf, CanRequestId rid, const StringRef& reply, uint8_t *extra, CanMessageType replyType, function_ref_noexcept<void(const CanMessageBuffer*) noexcept> callback) noexcept
794{
795 if (can0dev == nullptr)
796 {
797 // Transactions sometimes get requested after we have shut down CAN, e.g. when we destroy filament monitors
798 CanMessageBuffer::Free(buf);
799 return GCodeResult::error;
800 }
801
802 const CanAddress dest = buf->id.Dst();
803 const CanMessageType msgType = buf->id.MsgType(); // save for possible error message
804
805 {
806 // This code isn't re-entrant and it can get called from a task other than Main to shut the system down, so we need to use a mutex
807 MutexLocker lock(transactionMutex);
808
809 SendCanMessage(TxBufferIndexRequest, MaxRequestSendWait, buf);
810 reprap.GetPlatform().OnProcessingCanMessage();
811
812 const uint32_t whenStartedWaiting = millis();
813 uint32_t timeWaiting = 0;
814 unsigned int fragmentsReceived = 0;
815 for (;;)
816 {
817 const uint32_t timeout = (timeWaiting < UsualResponseTimeout) ? UsualResponseTimeout - timeWaiting : 1;
818 if (!can0dev->ReceiveMessage(RxBufferIndexResponse, timeout, buf))
819 {
820 break;
821 }
822
823 if (reprap.Debug(Module::CAN))
824 {
825 buf->DebugPrint("Rx1:");
826 }
827
828 // The following code allows for the possibility of receiving a StandardReply (e.g. because an error occurred) when we were expecting a different reply.
829 // It assumes that any custom reply we may want has the requestId in the same place as a StandardReply.
830 const bool matchesRequest = buf->id.Src() == dest
831 && (buf->msg.standardReply.requestId == rid || buf->msg.standardReply.requestId == CanRequestIdAcceptAlways);
832 if (matchesRequest && buf->id.MsgType() == CanMessageType::standardReply && buf->msg.standardReply.fragmentNumber == fragmentsReceived)
833 {
834 if (fragmentsReceived == 0)
835 {
836 const size_t textLength = buf->msg.standardReply.GetTextLength(buf->dataLength);
837 if (textLength != 0) // avoid concatenating blank lines to existing output
838 {
839 reply.lcatn(buf->msg.standardReply.text, textLength);
840 }
841 if (extra != nullptr)
842 {
843 *extra = buf->msg.standardReply.extra;
844 }
845 uint32_t waitedFor = millis() - whenStartedWaiting;
846 if (waitedFor > longestWaitTime)
847 {
848 longestWaitTime = waitedFor;
849 longestWaitMessageType = (uint16_t)msgType;
850 }

Callers

nothing calls this directly

Calls 6

SendCanMessageFunction · 0.85
DebugMethod · 0.80
lcatfMethod · 0.80
DebugPrintMethod · 0.45
MessageFMethod · 0.45

Tested by

no test coverage detected