bool ComplexDomainFlux::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
  {
    assert(inp.size()==1);
    InputBuffer* in = inp[0].data;
    assert(outp.size()==1);
    OutputBuffer* out = outp[0].data;

    if ((out->tokenno()==0) && (in->tokenno()!=-2))
      in->prependZeros(2);
    if (!in->hasTokens(3)) return false;

    const int N = in->info().size/2;
    ArrayXcd inPredPredRotator(N);
    ArrayXcd inPredRotator(N);
    rotatorOp<double> op;
    {
      Map<ArrayXcd> inPredPredData((complex<double>*) in->token(0),N);
      inPredPredRotator = inPredPredData.unaryExpr(op);
    }
    while (in->hasTokens(3))
    {
      Map<ArrayXcd> inPredData((complex<double>*) in->token(1),N);
      Map<ArrayXcd> inData((complex<double>*) in->token(2), N);
      inPredRotator = inPredData.unaryExpr(op);
      double* output = out->writeToken();
      *output++ = (inData - (inPredData * (inPredRotator * inPredPredRotator.conjugate()))).abs().sum();
      in->consumeToken();
      inPredPredRotator.swap(inPredRotator);
    }

    return true;
  }
Exemple #2
0
bool test_accept(LocalNode &node)
        throw (EpiException)
{

    node.publishPort();

    std::auto_ptr<Connection> connection(node.accept());
    std::auto_ptr<MailBox> mailbox(node.createMailBox(connection.get()));
    connection->start();

    std::auto_ptr<ErlangMessage> msg;
    ErlTerm* received_term;
    OutputBuffer *buffer = mailbox->newOutputBuffer();

    bool loop = true;
    while (loop) {
        msg.reset(mailbox->receiveMsg());

        if (!(msg->messageType() == ERL_MSG_SEND ||
              msg->messageType() == ERL_MSG_REG_SEND)) {
            std::cout << "Message is not SEND type\n";
            return false;
        }

        received_term = msg->getMsg();

        if (msg->messageType() == ERL_MSG_REG_SEND) {
            std::cout << "Received to " << ((RegSendMessage *) msg.get())->getRecipientName() <<
                    ": " << received_term->toString() << "\n";
        } else {
            std::cout << "Received to " << ((SendMessage *) msg.get())->getRecipientPid()->toString() <<
                    ": " << received_term->toString() << "\n";
        }

        if (received_term->instanceOf(ERL_TUPLE)) {
            ErlTuple *tuple = (ErlTuple *) received_term;
            if (tuple->arity() == 2) {
                ErlTerm* term1 = tuple->elementAt(0);
                ErlTerm* term2 = tuple->elementAt(1);
                if (term1->instanceOf(ERL_PID)) {

                    std::cout << "Sending " << term2->toString() <<
                            " to " << term1->toString() << "\n";

                    buffer->reset();
                    buffer->writeTerm(term2);
                    mailbox->sendBuf((ErlPid *) term1, buffer);
                    std::cout << "Sent.\n";
                }
            }
        }

        if (received_term->instanceOf(ERL_ATOM)) {
            if (((ErlAtom *) received_term)->atomValue() == "exit") {
                loop = false;
            }
        }
    }
    return true;
}
Exemple #3
0
bool Flux::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;

	if ((out->tokenno()==0) && (in->tokenno()!=-1))
		in->prependZeros(1);
	if (!in->hasTokens(2))
		return false;

	const int N = in->info().size;
    double lastNorm = 0.0;
    double nextNorm = Map<VectorXd>(in->token(0),N).norm();
    while (in->hasTokens(2))
    {
    	Map<VectorXd> last(in->token(0),N);
        lastNorm = nextNorm;
        Map<VectorXd> next(in->token(1),N);
        nextNorm = next.norm();
        double* output = out->writeToken();
        if (lastNorm*nextNorm==0)
        	*output = 0.0;
        else if (m_onlyIncrease)
        	*output = (next-last).unaryExpr(filterNegativeOp<double>()).squaredNorm() / (lastNorm*nextNorm);
		else
			*output = (next - last).squaredNorm() / (lastNorm * nextNorm);

        in->consumeToken();
    }
    return true;
}
bool Variation::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	if (!in->hasTokens(2)) return false;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;

	if ((out->tokenno()==0) && (in->tokenno()!=-1))
		in->prependZeros(1);

	const int N = in->info().size;
    double lastNorm = 0.0;
    double nextNorm = Map<VectorXd>(in->token(0),N).norm();
    while (in->hasTokens(2))
    {
    	Map<VectorXd> last(in->token(0),N);
        lastNorm = nextNorm;
        Map<VectorXd> next(in->token(1),N);
        nextNorm = next.norm();
        if (lastNorm*nextNorm !=0)
        	lastNorm = 1 - last.dot(next) / (lastNorm * nextNorm);
        else
        	lastNorm = 0.0;
        out->write(&lastNorm,1);
        in->consumeToken();
    }
    return true;
}
void Webserver::HandleGCodeReply(const WebSource source, const char *reply)
{
	switch (source)
	{
	case WebSource::HTTP:
		if (numSessions > 0)
		{
			OutputBuffer *buffer = gcodeReply->GetLastItem();
			if (buffer == nullptr || buffer->IsReferenced())
			{
				if (!OutputBuffer::Allocate(buffer))
				{
					// No more space available, stop here
					return;
				}
				gcodeReply->Push(buffer);
			}

			buffer->cat(reply);
			seq++;
		}
		break;

	case WebSource::Telnet:
	default:
		break;
	}
}
bool SpectralCrestFactorPerBand::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	if (in->empty()) return false;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;

	int nbBands = m_band.size();
    double* tmp = new double[in->info().size];
    while (!in->empty())
    {
    	double* inData = in->readToken();
    	double* output = out->writeToken();
    	for (int k=0;k<nbBands;++k)
    	{
    		bandinfo& bi = m_band[k];
    		double* data = &inData[bi.start];
    		int datalen = bi.length();
    		if (bi.group>1) // grpsize > 1
    		{
    			data = tmp;
    			datalen /= bi.group;
    			double* ptr = &inData[bi.start];
    			for (int d=0;d<datalen;d++) {
    				double s = 0;
    				for (int g=0;g<bi.group;g++)
    					s += *ptr++;
    				data[d] = s;
    			}
    		}
    		double am = 0;
    		double maxdata = data[0];
    		for (int i=0;i<datalen;i++)
    		{
    			am += data[i];
    			if (data[i]>maxdata) {
    				maxdata = data[i];
    			}
    		}
    		if (am!=0) {
    			output[k] = maxdata * datalen / am;
    			continue;
    		}
    		output[k] = maxdata / EPS;
    	}

        in->consumeToken();
    }
    delete [] tmp;

    return true;
}
Exemple #7
0
  bool AudioFileReader::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
  {
    assert(inp.size()==0);
    assert(outp.size()==1);
    OutputBuffer* out = outp[0].data;

    int nbRead = readFramesIntoBuffer();
    if (nbRead==0)
      return false;
    if (m_rescale)
      for (int i=0;i<nbRead;i++)
        m_readBuffer[i] = (m_readBuffer[i] - m_mean) * m_factor;
    out->write(m_readBuffer,nbRead);
    return true;
  }
bool AC2LPC::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;

    assert(out->info().size==m_nbCoeffs);
    assert(in->info().size>m_nbCoeffs);
    while (!in->empty())
    {
        ac2lpc(in->readToken(),out->writeToken(),m_nbCoeffs);
        in->consumeToken();
    }
    return true;
}
Exemple #9
0
	/**
	 * Add text to the output storage.
	 * @param text   Text to store.
	 * @param length Length of the text in bytes, \c 0 means 'length of the string'.
	 */
	void Add(const char *text, int length = 0)
	{
		if (length == 0) length = strlen(text);

		if (length > 0 && this->BufferHasRoom()) {
			int stored_size = this->output_buffer[this->output_buffer.Length() - 1].Add(text, length);
			length -= stored_size;
			text += stored_size;
		}
		while (length > 0) {
			OutputBuffer *block = this->output_buffer.Append();
			block->Clear(); // Initialize the new block.
			int stored_size = block->Add(text, length);
			length -= stored_size;
			text += stored_size;
		}
	}
Exemple #10
0
// Get the list of files in the specified directory in JSON format.
// If flagDirs is true then we prefix each directory with a * character.
OutputBuffer *RepRap::GetFilesResponse(const char *dir, bool flagsDirs)
{
	// Need something to write to...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		return nullptr;
	}

	response->copy("{\"dir\":");
	response->EncodeString(dir, strlen(dir), false);
	response->cat(",\"files\":[");

	FileInfo fileInfo;
	bool firstFile = true;
	bool gotFile = platform->GetMassStorage()->FindFirst(dir, fileInfo);
	size_t bytesLeft = OutputBuffer::GetBytesLeft(response);	// don't write more bytes than we can
	char filename[FILENAME_LENGTH];
	filename[0] = '*';
	const char *fname;

	while (gotFile)
	{
		if (fileInfo.fileName[0] != '.')			// ignore Mac resource files and Linux hidden files
		{
			// Get the long filename if possible
			if (flagsDirs && fileInfo.isDirectory)
			{
				strncpy(filename + sizeof(char), fileInfo.fileName, FILENAME_LENGTH - 1);
				filename[FILENAME_LENGTH - 1] = 0;
				fname = filename;
			}
			else
			{
				fname = fileInfo.fileName;
			}

			// Make sure we can end this response properly
			if (bytesLeft < strlen(fname) * 2 + 4)
			{
				// No more space available - stop here
				break;
			}

			// Write separator and filename
			if (!firstFile)
			{
				bytesLeft -= response->cat(',');
			}
			bytesLeft -= response->EncodeString(fname, FILENAME_LENGTH, false);

			firstFile = false;
		}
		gotFile = platform->GetMassStorage()->FindNext(fileInfo);
	}
	response->cat("]}");

	return response;
}
bool Difference::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	if (in->empty()) return false;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;

	const int N = in->info().size - 1;
	while (!in->empty())
	{
		double* inData = in->readToken();
		double* outData = out->writeToken();
		for (int i=0;i<N;i++)
			outData[i] = inData[i+1] - inData[i];
		in->consumeToken();
	}
    return true;
}
Exemple #12
0
  bool Cepstrum::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
  {
    assert(inp.size()==1);
    InputBuffer* in = inp[0].data;
    if (in->empty())
      return false;
    assert(outp.size()==1);
    OutputBuffer* out = outp[0].data;

    safeLogOp<double> slop;
    VectorXd outDct;
    while (!in->empty())
    {
      Map<VectorXd> inData(in->readToken(),in->info().size);
      outDct.noalias() = m_dctPlan * inData.unaryExpr(slop);
      memcpy(out->writeToken(),outDct.data() + m_ignoreFirst, out->info().size*sizeof(double));
      in->consumeToken();
    }
    return true;
  }
Exemple #13
0
  bool SpecificLoudness::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
  {
    assert(inp.size()==1);
    InputBuffer* in = inp[0].data;
    if (in->empty()) return false;
    assert(outp.size()==1);
    OutputBuffer* out = outp[0].data;

    const int N = in->info().size;
    const int M = out->info().size;
    while (!in->empty())
    {
      Map<VectorXd> inData(in->readToken(),N);
      double* outData = out->writeToken();
      for (int i=0;i<NB_BARK_BANDS;i++)
        outData[i] = pow(inData.segment(m_bkBdLimits[i],m_bkBdLimits[i+1]-m_bkBdLimits[i]).sum(),0.23);
      in->consumeToken();
    }

    return true;
  }
Exemple #14
0
  bool MelFilterBank::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
  {
    assert(inp.size()==1);
    InputBuffer* in = inp[0].data;
    if (in->empty()) return false;
    assert(outp.size()==1);
    OutputBuffer* out = outp[0].data;

    while (!in->empty()) {
      Map<VectorXd> inData(in->readToken(),in->info().size);
      double* outData = out->writeToken();
      for (int f=0;f<m_filters.size();f++)
      {
        RowVectorXd& filter = m_filters[f];
        outData[f] = filter * inData.segment(m_filterStart[f],filter.size());
      }
      in->consumeToken();
    }

    return true;
  }
bool FrameTokenizer::process(Ports<InputBuffer*>& inp, Ports<OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;
	assert(in->size()==1);

	if ((out->tokenno()==0) && (in->tokenno()!=-m_blockSize/2))
		in->prependZeros(m_blockSize/2);

	if (!in->hasTokens(m_blockSize))
		return false;

	while (in->hasTokens(m_blockSize)) {
		in->read(out->writeToken(),m_blockSize);
		in->consumeTokens(m_stepSize);
	}

	return true;
}
bool AdvancedFrameTokenizer::process(YAAFE::Ports<YAAFE::InputBuffer*>& inp, YAAFE::Ports<YAAFE::OutputBuffer*>& outp)
{
	assert(inp.size()==1);
	InputBuffer* in = inp[0].data;
	assert(outp.size()==1);
	OutputBuffer* out = outp[0].data;
	assert(in->size()==1);

	if ((out->tokenno()==0) && (in->tokenno()!=-m_blockSize/2))
		in->prependZeros(m_blockSize/2);

	if (!in->hasTokens(m_blockSize))
		return false;

	while (in->hasTokens(m_blockSize)) {
		in->read(out->writeToken(),m_blockSize);
		int nextInputToken = (int) floor(out->tokenno() * m_outStepSize * in->info().sampleRate / m_outSampleRate + 0.5);
		in->consumeTokens(nextInputToken - m_blockSize/2 - in->tokenno());
	}

	return true;
}
Exemple #17
0
// Test send and receive with a reply server.
bool send_reply_server(ErlTerm *t, MailBox *mailbox)
        throw(EpiException)
{

    std::cout << "Sending term: " << t->toString() << "\n";

    OutputBuffer *buffer = mailbox->newOutputBuffer();

    // Create tuple with pid
    ErlPid *pid = mailbox->self();
    ErlTermPtr<ErlTuple> tuple(new ErlTuple(pid, t));

    buffer->writeTerm(tuple.get());

    mailbox->sendBuf("reply_server", buffer);

    std::cout << "Sent. Receiving response:\n";

    std::auto_ptr<EpiMessage> msg(mailbox->receiveMsg());

    if (msg->messageType() != ERL_MSG_SEND) {
        std::cout << "Message is not SEND type\n";
        return false;
    }

    ErlTerm* t2 = ((ErlangMessage *) msg.get())->getMsg();

    std::cout << "Got term: " << t2->toString() << "\n";

    bool equals = t->equals(*t2);
    if (equals) {
        std::cout << "Equals, ok" << "\n";
    } else {
        std::cout << "Not equals, error!" << "\n";
    }
    return equals;
}
void decompress(InputStream& inputStream, OutputBuffer& output, header* pHeader) {

	header h;
	if (pHeader) {
		h = *pHeader;
	} else {
		readHeader(inputStream, h);
	}

	uint8* pInputBuffer	 = new uint8[h.fileSize];
	uint8* pOutputBuffer = new uint8[h.fileSize];

	ArithmeticDecoder	decoder(inputStream);
	StructuredModel		model(h.increments);
	model.decode(decoder, pInputBuffer, h.tempSize);

	iMTF(pInputBuffer, h.tempSize);
	iBWT(pInputBuffer, pOutputBuffer, h.tempSize, h.first);
	iRLE(pOutputBuffer, pInputBuffer, h.tempSize);

	output.setBuffer(pInputBuffer, h.fileSize);
	delete[] pOutputBuffer;
}
Exemple #19
0
Result<Ok, nsresult>
WritableSharedMap::Serialize()
{
  // Serializes a new snapshot of the map, initializes a new read-only shared
  // memory region with its contents, and updates all entries to point to that
  // new snapshot.
  //
  // The layout of the snapshot is as follows:
  //
  // - A header containing a uint32 count field containing the number of
  //   entries in the map, followed by that number of serialized entry headers,
  //   as produced by Entry::Code.
  //
  // - A data block containing structured clone data for each of the entries'
  //   values. This data is referenced by absolute byte offsets from the start
  //   of the shared memory region, encoded in each of the entry header values.
  //   Each entry's data is aligned to kStructuredCloneAlign, and therefore may
  //   have alignment padding before it.
  //
  // This serialization format is decoded by the MaybeRebuild() method of
  // read-only SharedMap() instances, and used to populate their mEntries
  // hashtables.
  //
  // Writable instances never read the header blocks, but instead directly
  // update their Entry instances to point to the appropriate offsets in the
  // shared memory region created by this function.

  uint32_t count = mEntries.Count();

  size_t dataSize = 0;
  size_t headerSize = sizeof(count);
  size_t blobCount = 0;

  for (auto& entry : IterHash(mEntries)) {
    headerSize += entry->HeaderSize();
    blobCount += entry->BlobCount();

    dataSize += entry->Size();
    AlignTo(&dataSize, kStructuredCloneAlign);
  }

  size_t offset = headerSize;
  AlignTo(&offset, kStructuredCloneAlign);

  OutputBuffer header;
  header.codeUint32(count);

  MemMapSnapshot mem;
  MOZ_TRY(mem.Init(offset + dataSize));

  auto ptr = mem.Get<char>();

  // We need to build the new array of blobs before we overwrite the existing
  // one, since previously-serialized entries will store their blob references
  // as indexes into our blobs array.
  nsTArray<RefPtr<BlobImpl>> blobImpls(blobCount);

  for (auto& entry : IterHash(mEntries)) {
    AlignTo(&offset, kStructuredCloneAlign);

    size_t blobOffset = blobImpls.Length();
    if (entry->BlobCount()) {
      blobImpls.AppendElements(entry->Blobs());
    }

    entry->ExtractData(&ptr[offset], offset, blobOffset);
    entry->Code(header);

    offset += entry->Size();
  }

  mBlobImpls = std::move(blobImpls);

  // FIXME: We should create a separate OutputBuffer class which can encode to
  // a static memory region rather than dynamically allocating and then
  // copying.
  MOZ_ASSERT(header.cursor() == headerSize);
  memcpy(ptr.get(), header.Get(), header.cursor());

  // We've already updated offsets at this point. We need this to succeed.
  mMap.reset();
  MOZ_RELEASE_ASSERT(mem.Finalize(mMap).isOk());

  return Ok();
}
Exemple #20
0
int main(int argc, char* argv[])
{
    // Check for correct number of arguments
    if(argc != 3)
    {
        cerr << "Invalid number of arguments"<<std::endl;
        return 1;
    }
    
    // set up UDP socket, including BINDING hints, IP, and port number
    int sockfd;
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("Can't create socket");
        exit(-1);
    }
    
    int maxSockfd = sockfd;
    char serverIP[20];
    struct addrinfo hints;
    struct addrinfo* res;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET; // IPv4
    hints.ai_socktype = SOCK_DGRAM;
    
    int portno = atoi(argv[1]);
    cout << "port number is " << portno<<endl;
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(portno);     // short, network byte order
    addr.sin_addr.s_addr = inet_addr("10.0.0.1");
    memset(addr.sin_zero, '\0', sizeof(addr.sin_zero));
    
    
    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind");
        return 2;
    }
    
    HeaderPacket req_pkt_syn;
    struct sockaddr_in clientAddr;
    socklen_t clilen = sizeof(clientAddr);

    OutputBuffer mybuffer;
    mybuffer.setup();
    uint16_t state = NO_CONNECTION;
    
    if(recvfrom(sockfd, &req_pkt_syn, sizeof(req_pkt_syn), 0, (struct sockaddr*) &clientAddr, (socklen_t*) &clilen) < 0)
    {
        cerr << "recvfrom failed" << endl;
        return 1;
    }
    else
    {
      
        if(ntohs(req_pkt_syn.m_flags) != SYN)
        {
            cerr << "Received a packet that's not SYN, cannot set up connection" <<endl;
            return 1;
        }
        uint16_t initseq = genRandom();
        
        // sending out SYNACK packet
        HeaderPacket resp_pkt_synack;
        resp_pkt_synack.m_seq = htons(initseq);
        resp_pkt_synack.m_ack = htons(0); //server does not need to ack with anything
        resp_pkt_synack.m_flags = htons(SYNACK); //SYNACK flag
        //resp_pkt_synack.m_window = htons(RECV_WINDOW);
        
        if(sendto(sockfd, &resp_pkt_synack, sizeof(resp_pkt_synack), 0, (struct sockaddr*) &clientAddr, clilen)<0)
        {
            cerr << "Sendto fails" << endl;
            return 1;
        }
        state = SYNACK_SENT;
    }
    
    fd_set readFds;
    fd_set writeFds;
    fd_set errFds;
    fd_set watchFds;
    FD_ZERO(&readFds);
    FD_ZERO(&writeFds);
    FD_ZERO(&errFds);
    FD_ZERO(&watchFds);
    
    FileReader myreader;
    myreader.openfile(argv[2]);
    
    bool finish = false;
    
    
    double sRTT = 3;
    double devRtt = 3;

    struct timeval tv;
   
    
    if(!FD_ISSET(sockfd, &readFds))
        FD_SET(sockfd, &readFds);

    while (true) {
        int nReadyFds = 0;
        errFds = watchFds;
        if(!FD_ISSET(sockfd, &watchFds))
            FD_SET(sockfd, &watchFds);
        
        tv.tv_sec = 0;
        tv.tv_usec = 500000;
        if(finish)
        {
            cout << "Time to close the connection"<<endl;
            //close(sockfd);
            break;
        }

        if ((nReadyFds = select(maxSockfd+1, &readFds, &writeFds, &errFds, &tv)) == -1) {
            perror("select");
            return 4;
        }
        
        if (nReadyFds == 0) {
            cout << "TIMEOUT HAPPENS" <<endl;
            if(state == SYNACK_SENT)
            {
                HeaderPacket resp_pkt_synack;
                uint16_t seq = mybuffer.getNextSeqNo();
                cout << "Send out SYNACK packet "<< seq << "Retransmit "<<endl;
                resp_pkt_synack.m_seq = htons(seq);
                resp_pkt_synack.m_ack = htons(0);
                resp_pkt_synack.m_flags = htons(SYNACK); //SYNACK flag
                //resp_pkt_synack.m_window = htons(mybuffer.getWindowSize());
                if(sendto(sockfd, &resp_pkt_synack, sizeof(resp_pkt_synack), 0, (struct sockaddr*) &clientAddr, clilen)<0)
                {
                    cerr << "Sendto fails" << endl;
                    return 1;
                }
                 FD_SET(sockfd, &readFds);
            }
            else if (state == SENT_FIN)
            {
                HeaderPacket resp_pkt_fin;
                resp_pkt_fin.m_seq = htons(mybuffer.getNextSeqNo());
                resp_pkt_fin.m_flags = htons(FIN); //FIN flag
                resp_pkt_fin.m_ack = htons(0);
                //resp_pkt_fin.m_window = htons(mybuffer.getWindowSize());
                
                if(sendto(sockfd, &resp_pkt_fin, sizeof(resp_pkt_fin), 0, (struct sockaddr*) &clientAddr, clilen)<0)
                {
                    cerr << "Sendto fails" << endl;
                    return 1;
                }
                 FD_SET(sockfd, &readFds);
                
            }
            else if (state == CONNECTED)
            {
                if(mybuffer.timeout())
                {
                    FD_CLR(sockfd, &readFds);
                    //close after several retrials
                    close(sockfd);
                    break;
                }
                else
                {
                    myreader.truncate(mybuffer.window_size());
                    uint16_t seq = mybuffer.retcumulative();
                    HeaderPacket res_pkt = mybuffer.getPkt(seq);
                    res_pkt.m_seq = htons(seq);
                    res_pkt.m_flags = htons(0x0);
                    cout << "Sending data packet " << seq << " retransmit " <<endl;
                    if(sendto(sockfd, &res_pkt, sizeof(res_pkt), 0, (struct sockaddr*) &clientAddr, clilen)<0)
                    {
                        cerr << "Sendto fails" << endl;
                        return 1;
                    }
                    FD_SET(sockfd, &readFds);
                }
            }
        }
        else
        {
            for(int fd = 0; fd <= maxSockfd; fd++){
                if (FD_ISSET(fd, &readFds)) // reading, recvfrom cases
                {
                    HeaderPacket req_pkt;
                    if(recvfrom(fd, &req_pkt, sizeof(req_pkt), 0, (struct sockaddr*) &clientAddr, (socklen_t*) &clilen) < 0)
                    {
                        cerr << "recvfrom failed" << endl;
                        return 1;
                    }
                    else
                    {
                        switch(ntohs(req_pkt.m_flags))
                        {
                            case SYNACK:
                            {
                                cout << "Receiveing SYNACK packet "<< ntohs(req_pkt.m_ack)<<endl;
                                mybuffer.setInitSeq(ntohs(req_pkt.m_ack));
                                if(myreader.hasMore())
                                {
                                    
                                    mybuffer.insert(myreader.top());
                                    myreader.pop();
                                }
                                else
                                {
                                    cout <<"nomore"<<endl;
                                }
                                state = CONNECTED;
                                FD_CLR(fd, &readFds);
                                FD_SET(fd, &writeFds);
                                break;
                            }
                            case ACK:
                            {
                                cout << "Receiving ACK packet "<< ntohs(req_pkt.m_ack)<<endl;
                                mybuffer.ack(ntohs(req_pkt.m_ack));
                                
                                /*
                                clock_t end = clock();
                                //reset the timeout
                                double sampleRTT = mybuffer.get_duration(ntohs(req_pkt.m_ack), end);
                                //now update the waiting time
                                
                                double difference = sampleRTT - sRTT;
                                sRTT = sRTT + 0.125 * (difference);
                                devRtt = devRtt + 0.25 * (abs(difference) - devRtt);
                                double ret_to = sRTT + 4* devRtt;
                                
                                double intpart, fracpart;
                                fracpart = modf(ret_to, &intpart);
                                tv.tv_sec = (time_t) intpart;
                                tv.tv_usec = (time_t) 1000000*fracpart;
                                */
                                while(myreader.hasMore() && mybuffer.hasSpace(strlen(myreader.top().payload)))
                                {
                                    cout << "let's do some insert" <<endl;
                                    mybuffer.insert(myreader.top());
                                    myreader.pop();
                                }
                                if(!mybuffer.hasNext())
                                {
                                    cout <<"change state to finish"<<endl;
                                    state = SENT_FIN;
                                }
                            
                                //don't do write until you ack all the packets you just sent out
                                if(mybuffer.switch_to_write())
                                {
                                    cout << "SWITCH TO WRITE STATE " <<endl;
                                    FD_CLR(fd, &readFds);
                                    FD_SET(fd, &writeFds);
                                }
                                break;
                            }
                            case FINACK:
                            {
                                cout << "Receiving FINACK packet "<< ntohs(req_pkt.m_ack)<<endl;
                                finish = true;
                                FD_CLR(fd, &readFds);
                                break;
                            }
                            default:
                                break;
                        }
                    }
                    
                }
                
                else if(FD_ISSET(fd, &writeFds)) // writing, sendto cases
                {
                        cout <<"Do some write" <<endl;

                        HeaderPacket res_pkt;
                        switch(state)
                        {
                            case CONNECTED:
                            {
                                uint16_t seq = mybuffer.getNextSeqNo();
                                res_pkt = mybuffer.getPkt(seq); // initial sequence number
                            
                               // clock_t t = clock();
                                
                                ///mybuffer.record_start(seq, clock());
                                
                                cout << "Sending data packet " << seq << endl;
                                
                                /*
                                cout << "print out payload" <<endl;
                                int p_size = strlen(res_pkt.payload);
                                if(p_size >1024)
                                    p_size = 1024;
                                for (int i = 0; i<p_size; i++) {
                                    cout << res_pkt.payload[i];
                                }
                                cout << endl;
                                */
                                
                                res_pkt.m_flags = htons(0x0);
                                if(sendto(sockfd, &res_pkt, sizeof(res_pkt), 0, (struct sockaddr*) &clientAddr, clilen)<0)
                                {
                                    cerr << "Sendto fails" << endl;
                                    return 1;
                                }
                                if(mybuffer.switch_to_read())
                                {
                                    cout << "SWITCH TO READ STATE" <<endl;
                                    FD_CLR(fd, &writeFds);
                                    FD_SET(fd, &readFds);
                                }
                                break;
                            }
                            case SENT_FIN:
                            {
                                uint16_t seq = mybuffer.retcumulative();
                                res_pkt.m_seq = htons(seq);
                                //res_pkt.m_window = htons(getWindowSize());
                                res_pkt.m_ack = htons(0);
                                res_pkt.m_flags = htons(FIN);
                                cout << "Sending FIN packet " << seq << endl;
                                if(sendto(sockfd, &res_pkt, sizeof(res_pkt), 0, (struct sockaddr*) &clientAddr, clilen)<0)
                                {
                                    cerr << "Sendto fails" << endl;
                                    return 1;
                                }
                                FD_CLR(fd, &writeFds);
                                FD_SET(fd, &readFds);
                                break;
                            }
                        }
                            
                    }
            }
        }
     }
    
    close(sockfd);
    }
Exemple #21
0
OutputBuffer *RepRap::GetConfigResponse()
{
	// We need some resources to return a valid config response...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		return nullptr;
	}

	const size_t numAxes = reprap.GetGCodes()->GetNumAxes();

	// Axis minima
	response->copy("{\"axisMins\":");
	char ch = '[';
	for (size_t axis = 0; axis < numAxes; axis++)
	{
		response->catf("%c%.2f", ch, platform->AxisMinimum(axis));
		ch = ',';
	}

	// Axis maxima
	response->cat("],\"axisMaxes\":");
	ch = '[';
	for (size_t axis = 0; axis < numAxes; axis++)
	{
		response->catf("%c%.2f", ch, platform->AxisMaximum(axis));
		ch = ',';
	}

	// Accelerations
	response->cat("],\"accelerations\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->Acceleration(drive));
		ch = ',';
	}

	// Motor currents
	response->cat("],\"currents\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->GetMotorCurrent(drive, false));
		ch = ',';
	}

	// Firmware details
	response->catf("],\"firmwareElectronics\":\"%s", platform->GetElectronicsString());
#ifdef DUET_NG
	const char* expansionName = DuetExpansion::GetExpansionBoardName();
	if (expansionName != nullptr)
	{
		response->catf(" + %s", expansionName);
	}
#endif
	response->catf("\",\"firmwareName\":\"%s\"", FIRMWARE_NAME);
	response->catf(",\"firmwareVersion\":\"%s\"", VERSION);
#if defined(DUET_NG) && defined(DUET_WIFI)
	response->catf(",\"dwsVersion\":\"%s\"", network->GetWiFiServerVersion());
#endif
	response->catf(",\"firmwareDate\":\"%s\"", DATE);

	// Motor idle parameters
	response->catf(",\"idleCurrentFactor\":%.1f", platform->GetIdleCurrentFactor() * 100.0);
	response->catf(",\"idleTimeout\":%.1f", move->IdleTimeout());

	// Minimum feedrates
	response->cat(",\"minFeedrates\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->ConfiguredInstantDv(drive));
		ch = ',';
	}

	// Maximum feedrates
	response->cat("],\"maxFeedrates\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->MaxFeedrate(drive));
		ch = ',';
	}

	// Config file is no longer included, because we can use rr_configfile or M503 instead
	response->cat("]}");

	return response;
}
Exemple #22
0
// Get the JSON status response for the web server (or later for the M105 command).
// Type 1 is the ordinary JSON status response.
// Type 2 is the same except that static parameters are also included.
// Type 3 is the same but instead of static parameters we report print estimation values.
OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
{
	// Need something to write to...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		// Should never happen
		return nullptr;
	}

	// Machine status
	char ch = GetStatusCharacter();
	response->printf("{\"status\":\"%c\",\"coords\":{", ch);

	// Coordinates
	const size_t numAxes = reprap.GetGCodes()->GetNumAxes();
	{
		float liveCoordinates[DRIVES + 1];
#if SUPPORT_ROLAND
		if (roland->Active())
		{
			roland->GetCurrentRolandPosition(liveCoordinates);
		}
		else
#endif
		{
			move->LiveCoordinates(liveCoordinates, GetCurrentXAxes());
		}

		if (currentTool != nullptr)
		{
			const float *offset = currentTool->GetOffset();
			for (size_t i = 0; i < numAxes; ++i)
			{
				liveCoordinates[i] += offset[i];
			}
		}

		// Homed axes
		response->cat("\"axesHomed\":");
		ch = '[';
		for (size_t axis = 0; axis < numAxes; ++axis)
		{
			response->catf("%c%d", ch, (gCodes->GetAxisIsHomed(axis)) ? 1 : 0);
			ch = ',';
		}

		// Actual and theoretical extruder positions since power up, last G92 or last M23
		response->catf("],\"extr\":");		// announce actual extruder positions
		ch = '[';
		for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)
		{
			response->catf("%c%.1f", ch, liveCoordinates[numAxes + extruder]);
			ch = ',';
		}
		if (ch == '[')
		{
			response->cat(ch);
		}

		// XYZ positions
		response->cat("],\"xyz\":");
		if (!gCodes->AllAxesAreHomed() && move->IsDeltaMode())
		{
			// If in Delta mode, skip these coordinates if some axes are not homed
			response->cat("[0.00,0.00,0.00");
		}
		else
		{
			// On Cartesian printers, the live coordinates are (usually) valid
			ch = '[';
			for (size_t axis = 0; axis < numAxes; axis++)
			{
				response->catf("%c%.3f", ch, liveCoordinates[axis]);
				ch = ',';
			}
		}
	}

	// Current tool number
	const int toolNumber = (currentTool == nullptr) ? -1 : currentTool->Number();
	response->catf("]},\"currentTool\":%d", toolNumber);

	// Output - only reported once
	{
		bool sendBeep = (beepDuration != 0 && beepFrequency != 0);
		bool sendMessage = (message[0] != 0);
		if (sendBeep || sendMessage)
		{
			response->cat(",\"output\":{");

			// Report beep values
			if (sendBeep)
			{
				response->catf("\"beepDuration\":%d,\"beepFrequency\":%d", beepDuration, beepFrequency);
				if (sendMessage)
				{
					response->cat(",");
				}
				beepFrequency = beepDuration = 0;
			}

			// Report message
			if (sendMessage)
			{
				response->cat("\"message\":");
				response->EncodeString(message, ARRAY_SIZE(message), false);
				message[0] = 0;
			}
			response->cat("}");
		}
	}

	// Parameters
	{
		// ATX power
		response->catf(",\"params\":{\"atxPower\":%d", platform->AtxPower() ? 1 : 0);

		// Cooling fan value
		response->cat(",\"fanPercent\":");
		ch = '[';
		for(size_t i = 0; i < NUM_FANS; i++)
		{
			response->catf("%c%.2f", ch, platform->GetFanValue(i) * 100.0);
			ch = ',';
		}

		// Speed and Extrusion factors
		response->catf("],\"speedFactor\":%.2f,\"extrFactors\":", gCodes->GetSpeedFactor() * 100.0);
		ch = '[';
		for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)
		{
			response->catf("%c%.2f", ch, gCodes->GetExtrusionFactor(extruder) * 100.0);
			ch = ',';
		}
		response->cat((ch == '[') ? "[]" : "]");
		response->catf(",\"babystep\":%.03f}", gCodes->GetBabyStepOffset());
	}

	// G-code reply sequence for webserver (seqence number for AUX is handled later)
	if (source == ResponseSource::HTTP)
	{
		response->catf(",\"seq\":%d", webserver->GetReplySeq());

		// There currently appears to be no need for this one, so skip it
		//response->catf(",\"buff\":%u", webserver->GetGCodeBufferSpace(WebSource::HTTP));
	}

	/* Sensors */
	{
		response->cat(",\"sensors\":{");

		// Probe
		const int v0 = platform->GetZProbeReading();
		int v1, v2;
		switch (platform->GetZProbeSecondaryValues(v1, v2))
		{
			case 1:
				response->catf("\"probeValue\":%d,\"probeSecondary\":[%d]", v0, v1);
				break;
			case 2:
				response->catf("\"probeValue\":%d,\"probeSecondary\":[%d,%d]", v0, v1, v2);
				break;
			default:
				response->catf("\"probeValue\":%d", v0);
				break;
		}

		// Fan RPM
		response->catf(",\"fanRPM\":%d}", static_cast<unsigned int>(platform->GetFanRPM()));
	}

	/* Temperatures */
	{
		response->cat(",\"temps\":{");

		/* Bed */
		const int8_t bedHeater = heat->GetBedHeater();
		if (bedHeater != -1)
		{
			response->catf("\"bed\":{\"current\":%.1f,\"active\":%.1f,\"state\":%d},",
					heat->GetTemperature(bedHeater), heat->GetActiveTemperature(bedHeater),
					heat->GetStatus(bedHeater));
		}

		/* Chamber */
		const int8_t chamberHeater = heat->GetChamberHeater();
		if (chamberHeater != -1)
		{
			response->catf("\"chamber\":{\"current\":%.1f,", heat->GetTemperature(chamberHeater));
			response->catf("\"active\":%.1f,", heat->GetActiveTemperature(chamberHeater));
			response->catf("\"state\":%d},", static_cast<int>(heat->GetStatus(chamberHeater)));
		}

		/* Heads */
		{
			response->cat("\"heads\":{\"current\":");

			// Current temperatures
			ch = '[';
			for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%.1f", ch, heat->GetTemperature(heater));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");

			// Active temperatures
			response->catf(",\"active\":");
			ch = '[';
			for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");

			// Standby temperatures
			response->catf(",\"standby\":");
			ch = '[';
			for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");

			// Heater statuses (0=off, 1=standby, 2=active, 3=fault)
			response->cat(",\"state\":");
			ch = '[';
			for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%d", ch, static_cast<int>(heat->GetStatus(heater)));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");
		}
		response->cat("}}");
	}

	// Time since last reset
	response->catf(",\"time\":%.1f", platform->Time());

#if SUPPORT_SCANNER
	// Scanner
	if (scanner->IsEnabled())
	{
		response->catf(",\"scanner\":{\"status\":\"%c\"", scanner->GetStatusCharacter());
		response->catf(",\"progress\":%.1f}", scanner->GetProgress());
	}
#endif

	/* Extended Status Response */
	if (type == 2)
	{
		// Cold Extrude/Retract
		response->catf(",\"coldExtrudeTemp\":%1.f", heat->ColdExtrude() ? 0 : HOT_ENOUGH_TO_EXTRUDE);
		response->catf(",\"coldRetractTemp\":%1.f", heat->ColdExtrude() ? 0 : HOT_ENOUGH_TO_RETRACT);

		// Maximum hotend temperature - DWC just wants the highest one
		response->catf(",\"tempLimit\":%1.f", heat->GetHighestTemperatureLimit());

		// Endstops
		uint16_t endstops = 0;
		for(size_t drive = 0; drive < DRIVES; drive++)
		{
			EndStopHit stopped = platform->Stopped(drive);
			if (stopped == EndStopHit::highHit || stopped == EndStopHit::lowHit)
			{
				endstops |= (1 << drive);
			}
		}
		response->catf(",\"endstops\":%d", endstops);

		// Firmware name, machine geometry and number of axes
		response->catf(",\"firmwareName\":\"%s\",\"geometry\":\"%s\",\"axes\":%u", FIRMWARE_NAME, move->GetGeometryString(), numAxes);

		// Total and mounted volumes
		size_t mountedCards = 0;
		for(size_t i = 0; i < NumSdCards; i++)
		{
			if (platform->GetMassStorage()->IsDriveMounted(i))
			{
				mountedCards |= (1 << i);
			}
		}
		response->catf(",\"volumes\":%u,\"mountedVolumes\":%u", NumSdCards, mountedCards);

		// Machine name
		response->cat(",\"name\":");
		response->EncodeString(myName, ARRAY_SIZE(myName), false);

		/* Probe */
		{
			const ZProbeParameters probeParams = platform->GetCurrentZProbeParameters();

			// Trigger threshold
			response->catf(",\"probe\":{\"threshold\":%d", probeParams.adcValue);

			// Trigger height
			response->catf(",\"height\":%.2f", probeParams.height);

			// Type
			response->catf(",\"type\":%d}", platform->GetZProbeType());
		}

		/* Tool Mapping */
		{
			response->cat(",\"tools\":[");
			for(Tool *tool = toolList; tool != nullptr; tool = tool->Next())
			{
				// Heaters
				response->catf("{\"number\":%d,\"heaters\":[", tool->Number());
				for(size_t heater=0; heater<tool->HeaterCount(); heater++)
				{
					response->catf("%d", tool->Heater(heater));
					if (heater + 1 < tool->HeaterCount())
					{
						response->cat(",");
					}
				}

				// Extruder drives
				response->cat("],\"drives\":[");
				for(size_t drive=0; drive<tool->DriveCount(); drive++)
				{
					response->catf("%d", tool->Drive(drive));
					if (drive + 1 < tool->DriveCount())
					{
						response->cat(",");
					}
				}

				// Axis mapping. Currently we only map the X axis, but we return an array of arrays to allow for mapping other axes in future.
				response->cat("],\"axisMap\":[[");
				bool first = true;
				for (size_t xi = 0; xi < MAX_AXES; ++xi)
				{
					if ((tool->GetXAxisMap() & (1u << xi)) != 0)
					{
						if (first)
						{
							first = false;
						}
						else
						{
							response->cat(",");
						}
						response->catf("%u", xi);
					}
				}

				// Do we have any more tools?
				if (tool->Next() != nullptr)
				{
					response->cat("]]},");
				}
				else
				{
					response->cat("]]}");
				}
			}
			response->cat("]");
		}

		// MCU temperatures
#ifndef __RADDS__
		{
			float minT, currT, maxT;
			platform->GetMcuTemperatures(minT, currT, maxT);
			response->catf(",\"mcutemp\":{\"min\":%.1f,\"cur\":%.1f,\"max\":%.1f}", minT, currT, maxT);
		}
#endif

#ifdef DUET_NG
		// Power in voltages
		{
			float minV, currV, maxV;
			platform->GetPowerVoltages(minV, currV, maxV);
			response->catf(",\"vin\":{\"min\":%.1f,\"cur\":%.1f,\"max\":%.1f}", minV, currV, maxV);
		}
#endif
	}
	else if (type == 3)
	{
		// Current Layer
		response->catf(",\"currentLayer\":%d", printMonitor->GetCurrentLayer());

		// Current Layer Time
		response->catf(",\"currentLayerTime\":%.1f", printMonitor->GetCurrentLayerTime());

		// Raw Extruder Positions
		response->cat(",\"extrRaw\":");
		ch = '[';
		for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)		// loop through extruders
		{
			response->catf("%c%.1f", ch, gCodes->GetRawExtruderTotalByDrive(extruder));
			ch = ',';
		}
		if (ch == '[')
		{
			response->cat(ch);		// no extruders
		}

		// Fraction of file printed
		response->catf("],\"fractionPrinted\":%.1f", (printMonitor->IsPrinting()) ? (gCodes->FractionOfFilePrinted() * 100.0) : 0.0);

		// First Layer Duration
		response->catf(",\"firstLayerDuration\":%.1f", printMonitor->GetFirstLayerDuration());

		// First Layer Height
		// NB: This shouldn't be needed any more, but leave it here for the case that the file-based first-layer detection fails
		response->catf(",\"firstLayerHeight\":%.2f", printMonitor->GetFirstLayerHeight());

		// Print Duration
		response->catf(",\"printDuration\":%.1f", printMonitor->GetPrintDuration());

		// Warm-Up Time
		response->catf(",\"warmUpDuration\":%.1f", printMonitor->GetWarmUpDuration());

		/* Print Time Estimations */
		{
			// Based on file progress
			response->catf(",\"timesLeft\":{\"file\":%.1f", printMonitor->EstimateTimeLeft(fileBased));

			// Based on filament usage
			response->catf(",\"filament\":%.1f", printMonitor->EstimateTimeLeft(filamentBased));

			// Based on layers
			response->catf(",\"layer\":%.1f}", printMonitor->EstimateTimeLeft(layerBased));
		}
	}

	if (source == ResponseSource::AUX)
	{
		OutputBuffer *reply = platform->GetAuxGCodeReply();
		if (response != nullptr)
		{
			// Send the response to the last command. Do this last
			response->catf(",\"seq\":%u,\"resp\":", platform->GetAuxSeq());			// send the response sequence number

			// Send the JSON response
			response->EncodeReply(reply, true);										// also releases the OutputBuffer chain
		}
	}
	response->cat("}");

	return response;
}
Exemple #23
0
// Get a JSON-style filelist including file types and sizes
OutputBuffer *RepRap::GetFilelistResponse(const char *dir)
{
	// Need something to write to...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		return nullptr;
	}

	// If the requested volume is not mounted, report an error
	if (!platform->GetMassStorage()->CheckDriveMounted(dir))
	{
		response->copy("{\"err\":1}");
		return response;
	}

	// Check if the directory exists
	if (!platform->GetMassStorage()->DirectoryExists(dir))
	{
		response->copy("{\"err\":2}");
		return response;
	}

	response->copy("{\"dir\":");
	response->EncodeString(dir, strlen(dir), false);
	response->cat(",\"files\":[");

	FileInfo fileInfo;
	bool firstFile = true;
	bool gotFile = platform->GetMassStorage()->FindFirst(dir, fileInfo);
	size_t bytesLeft = OutputBuffer::GetBytesLeft(response);	// don't write more bytes than we can

	while (gotFile)
	{
		if (fileInfo.fileName[0] != '.')			// ignore Mac resource files and Linux hidden files
		{
			// Make sure we can end this response properly
			if (bytesLeft < strlen(fileInfo.fileName) + 70)
			{
				// No more space available - stop here
				break;
			}

			// Write delimiter
			if (!firstFile)
			{
				bytesLeft -= response->cat(',');
			}
			firstFile = false;

			// Write another file entry
			bytesLeft -= response->catf("{\"type\":\"%c\",\"name\":", fileInfo.isDirectory ? 'd' : 'f');
			bytesLeft -= response->EncodeString(fileInfo.fileName, FILENAME_LENGTH, false);
			bytesLeft -= response->catf(",\"size\":%u", fileInfo.size);

			const struct tm * const timeInfo = gmtime(&fileInfo.lastModified);
			if (timeInfo->tm_year <= /*19*/80)
			{
				// Don't send the last modified date if it is invalid
				bytesLeft -= response->cat('}');
			}
			else
			{
				bytesLeft -= response->catf(",\"date\":\"%04u-%02u-%02uT%02u:%02u:%02u\"}",
						timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday,
						timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
			}
		}
		gotFile = platform->GetMassStorage()->FindNext(fileInfo);
	}
	response->cat("]}");

	return response;
}
Exemple #24
0
// Get the JSON status response for PanelDue or the old web server.
// Type 0 was the old-style webserver status response, but is no longer supported.
// Type 1 is the new-style webserver status response.
// Type 2 is the M105 S2 response, which is like the new-style status response but some fields are omitted.
// Type 3 is the M105 S3 response, which is like the M105 S2 response except that static values are also included.
// 'seq' is the response sequence number, if it is not -1 and we have a different sequence number then we send the gcode response
OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
	// Need something to write to...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		// Should never happen
		return nullptr;
	}

	// Send the status. Note that 'S' has always meant that the machine is halted in this version of the status response, so we use A for pAused.
	char ch = GetStatusCharacter();
	if (ch == 'S')			// if paused then send 'A'
	{
		ch = 'A';
	}
	else if (ch == 'H')		// if halted then send 'S'
	{
		ch = 'S';
	}
	response->printf("{\"status\":\"%c\",\"heaters\":", ch);

	// Send the heater actual temperatures
	const int8_t bedHeater = heat->GetBedHeater();
	if (bedHeater != -1)
	{
		ch = ',';
		response->catf("[%.1f", heat->GetTemperature(bedHeater));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%.1f", ch, heat->GetTemperature(heater));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the heater active temperatures
	response->catf(",\"active\":");
	if (heat->GetBedHeater() != -1)
	{
		ch = ',';
		response->catf("[%.1f", heat->GetActiveTemperature(heat->GetBedHeater()));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the heater standby temperatures
	response->catf(",\"standby\":");
	if (bedHeater != -1)
	{
		ch = ',';
		response->catf("[%.1f", heat->GetStandbyTemperature(bedHeater));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the heater statuses (0=off, 1=standby, 2=active, 3 = fault)
	response->cat(",\"hstat\":");
	if (bedHeater != -1)
	{
		ch = ',';
		response->catf("[%d", static_cast<int>(heat->GetStatus(bedHeater)));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%d", ch, static_cast<int>(heat->GetStatus(heater)));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send XYZ positions
	const size_t numAxes = reprap.GetGCodes()->GetNumAxes();
	float liveCoordinates[DRIVES];
	reprap.GetMove()->LiveCoordinates(liveCoordinates, GetCurrentXAxes());
	const Tool* const currentTool = reprap.GetCurrentTool();
	if (currentTool != nullptr)
	{
		const float *offset = currentTool->GetOffset();
		for (size_t i = 0; i < numAxes; ++i)
		{
			liveCoordinates[i] += offset[i];
		}
	}
	response->catf(",\"pos\":");		// announce the XYZ position
	ch = '[';
	for (size_t drive = 0; drive < numAxes; drive++)
	{
		response->catf("%c%.3f", ch, liveCoordinates[drive]);
		ch = ',';
	}

	// Send extruder total extrusion since power up, last G92 or last M23
	response->cat("],\"extr\":");		// announce the extruder positions
	ch = '[';
	for (size_t drive = 0; drive < reprap.GetExtrudersInUse(); drive++)		// loop through extruders
	{
		response->catf("%c%.1f", ch, gCodes->GetRawExtruderPosition(drive));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the speed and extruder override factors
	response->catf(",\"sfactor\":%.2f,\"efactor\":", gCodes->GetSpeedFactor() * 100.0);
	ch = '[';
	for (size_t i = 0; i < reprap.GetExtrudersInUse(); ++i)
	{
		response->catf("%c%.2f", ch, gCodes->GetExtrusionFactor(i) * 100.0);
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the baby stepping offset
	response->catf(",\"babystep\":%.03f", gCodes->GetBabyStepOffset());

	// Send the current tool number
	const int toolNumber = (currentTool == nullptr) ? 0 : currentTool->Number();
	response->catf(",\"tool\":%d", toolNumber);

	// Send the Z probe value
	const int v0 = platform->GetZProbeReading();
	int v1, v2;
	switch (platform->GetZProbeSecondaryValues(v1, v2))
	{
	case 1:
		response->catf(",\"probe\":\"%d (%d)\"", v0, v1);
		break;
	case 2:
		response->catf(",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
		break;
	default:
		response->catf(",\"probe\":\"%d\"", v0);
		break;
	}

	// Send the fan settings, for PanelDue firmware 1.13 and later
	response->catf(",\"fanPercent\":");
	ch = '[';
	for (size_t i = 0; i < NUM_FANS; ++i)
	{
		response->catf("%c%.02f", ch, platform->GetFanValue(i) * 100.0);
		ch = ',';
	}

	// Send fan RPM value (we only support one)
	response->catf("],\"fanRPM\":%u", static_cast<unsigned int>(platform->GetFanRPM()));

	// Send the home state. To keep the messages short, we send 1 for homed and 0 for not homed, instead of true and false.
	response->cat(",\"homed\":");
	ch = '[';
	for (size_t axis = 0; axis < numAxes; ++axis)
	{
		response->catf("%c%d", ch, (gCodes->GetAxisIsHomed(axis)) ? 1 : 0);
		ch = ',';
	}
	response->cat(']');

	if (printMonitor->IsPrinting())
	{
		// Send the fraction printed
		response->catf(",\"fraction_printed\":%.4f", max<float>(0.0, gCodes->FractionOfFilePrinted()));
	}

	// Short messages are now pushed directly to PanelDue, so don't include them here as well
	// We no longer send the amount of http buffer space here because the web interface doesn't use these formns of status response

	if (type == 2)
	{
		if (printMonitor->IsPrinting())
		{
			// Send estimated times left based on file progress, filament usage, and layers
			response->catf(",\"timesLeft\":[%.1f,%.1f,%.1f]",
					printMonitor->EstimateTimeLeft(fileBased),
					printMonitor->EstimateTimeLeft(filamentBased),
					printMonitor->EstimateTimeLeft(layerBased));
		}
	}
	else if (type == 3)
	{
		// Add the static fields
		response->catf(",\"geometry\":\"%s\",\"axes\":%u,\"volumes\":%u,\"numTools\":%u,\"myName\":",
						move->GetGeometryString(), numAxes, NumSdCards, GetNumberOfContiguousTools());
		response->EncodeString(myName, ARRAY_SIZE(myName), false);
		response->cat(",\"firmwareName\":");
		response->EncodeString(FIRMWARE_NAME, strlen(FIRMWARE_NAME), false);
	}

	const int auxSeq = (int)platform->GetAuxSeq();
	if (type < 2 || (seq != -1 && auxSeq != seq))
	{

		// Send the response to the last command. Do this last because it can be long and may need to be truncated.
		response->catf(",\"seq\":%d,\"resp\":", auxSeq);					// send the response sequence number

		// Send the JSON response
		response->EncodeReply(platform->GetAuxGCodeReply(), true);			// also releases the OutputBuffer chain
	}

	response->cat("}");
	return response;
}
Exemple #25
0
int OutputBuffer::close_cb(void *context)
{
    OutputBuffer * p = reinterpret_cast<OutputBuffer*>(context);
    return (p->close() ? 0 : -1);
}
Exemple #26
0
int OutputBuffer::write_cb(void *context, const char *buffer, int len)
{
    OutputBuffer * p = reinterpret_cast<OutputBuffer*>(context);
    return (p->write(reinterpret_cast<const uint8_t*>(buffer), static_cast<size_t>(len)) ? len : -1);
}
Exemple #27
0
ln::String CSCommon::MakeXmlDocument(ln::Ref<DocumentSymbol> doc)
{
	OutputBuffer buffer;
	if (doc != nullptr)
	{
		buffer.append("/// <summary>").NewLine();
		buffer.AppendLinesHeaderd(doc->summary, "/// ").NewLine();
		buffer.append("/// </summary>").NewLine();

		for (auto& param : doc->params)
		{
			buffer.append("/// <param name=\"{0}\">", param->name).NewLine();
			buffer.AppendLinesHeaderd(param->description, "/// ").NewLine();
			buffer.append("/// </param>").NewLine();
		}

		if (!doc->returns.isEmpty())
		{
			buffer.append("/// <returns>").NewLine();
			buffer.AppendLinesHeaderd(doc->returns, "/// ").NewLine();
			buffer.append("/// </returns>").NewLine();
		}

		if (!doc->details.isEmpty())
		{
			buffer.append("/// <remarks>").NewLine();
			buffer.AppendLinesHeaderd(doc->details, "/// ").NewLine();
			buffer.append("/// </remarks>").NewLine();
		}
	}
	return buffer.toString();
}
Exemple #28
0
// Get the JSON status response for PanelDue or the old web server.
// Type 0 was the old-style webserver status response, but is no longer supported.
// Type 1 is the new-style webserver status response.
// Type 2 is the M105 S2 response, which is like the new-style status response but some fields are omitted.
// Type 3 is the M105 S3 response, which is like the M105 S2 response except that static values are also included.
// 'seq' is the response sequence number, if it is not -1 and we have a different sequence number then we send the gcode response
OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
	// Need something to write to...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		// Should never happen
		return nullptr;
	}

	// Send the status. Note that 'S' has always meant that the machine is halted in this version of the status response, so we use A for pAused.
	char ch = GetStatusCharacter();
	if (ch == 'S')			// if paused then send 'A'
	{
		ch = 'A';
	}
	else if (ch == 'H')		// if halted then send 'S'
	{
		ch = 'S';
	}
	response->printf("{\"status\":\"%c\",\"heaters\":", ch);

	// Send the heater actual temperatures
	const int8_t bedHeater = heat->GetBedHeater();
	if (bedHeater != -1)
	{
		ch = ',';
		response->catf("[%.1f", heat->GetTemperature(bedHeater));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%.1f", ch, heat->GetTemperature(heater));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the heater active temperatures
	response->catf(",\"active\":");
	if (heat->GetBedHeater() != -1)
	{
		ch = ',';
		response->catf("[%.1f", heat->GetActiveTemperature(heat->GetBedHeater()));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the heater standby temperatures
	response->catf(",\"standby\":");
	if (bedHeater != -1)
	{
		ch = ',';
		response->catf("[%.1f", heat->GetStandbyTemperature(bedHeater));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the heater statuses (0=off, 1=standby, 2=active)
	response->cat(",\"hstat\":");
	if (bedHeater != -1)
	{
		ch = ',';
		response->catf("[%d", static_cast<int>(heat->GetStatus(bedHeater)));
	}
	else
	{
		ch = '[';
	}
	for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
	{
		response->catf("%c%d", ch, static_cast<int>(heat->GetStatus(heater)));
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send XYZ positions
	float liveCoordinates[DRIVES];
	reprap.GetMove()->LiveCoordinates(liveCoordinates);
	const Tool* currentTool = reprap.GetCurrentTool();
	if (currentTool != nullptr)
	{
		const float *offset = currentTool->GetOffset();
		for (size_t i = 0; i < AXES; ++i)
		{
			liveCoordinates[i] += offset[i];
		}
	}
	response->catf(",\"pos\":");		// announce the XYZ position
	ch = '[';
	for (size_t drive = 0; drive < AXES; drive++)
	{
		response->catf("%c%.2f", ch, liveCoordinates[drive]);
		ch = ',';
	}

	// Send extruder total extrusion since power up, last G92 or last M23
	response->cat("],\"extr\":");		// announce the extruder positions
	ch = '[';
	for (size_t drive = 0; drive < reprap.GetExtrudersInUse(); drive++)		// loop through extruders
	{
		response->catf("%c%.1f", ch, gCodes->GetRawExtruderPosition(drive));
		ch = ',';
	}
	response->cat((ch == ']') ? "[]" : "]");

	// Send the speed and extruder override factors
	response->catf(",\"sfactor\":%.2f,\"efactor\":", gCodes->GetSpeedFactor() * 100.0);
	ch = '[';
	for (size_t i = 0; i < reprap.GetExtrudersInUse(); ++i)
	{
		response->catf("%c%.2f", ch, gCodes->GetExtrusionFactor(i) * 100.0);
		ch = ',';
	}
	response->cat((ch == '[') ? "[]" : "]");

	// Send the current tool number
	int toolNumber = (currentTool == nullptr) ? 0 : currentTool->Number();
	response->catf(",\"tool\":%d", toolNumber);

	// Send the Z probe value
	int v0 = platform->ZProbe();
	int v1, v2;
	switch (platform->GetZProbeSecondaryValues(v1, v2))
	{
	case 1:
		response->catf(",\"probe\":\"%d (%d)\"", v0, v1);
		break;
	case 2:
		response->catf(",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
		break;
	default:
		response->catf(",\"probe\":\"%d\"", v0);
		break;
	}

	// Send the fan0 settings (for PanelDue firmware 1.13)
	response->catf(",\"fanPercent\":[%.02f,%.02f]", platform->GetFanValue(0) * 100.0, platform->GetFanValue(1) * 100.0);

	// Send fan RPM value
	response->catf(",\"fanRPM\":%u", static_cast<unsigned int>(platform->GetFanRPM()));

	// Send the home state. To keep the messages short, we send 1 for homed and 0 for not homed, instead of true and false.
	if (type != 0)
	{
		response->catf(",\"homed\":[%d,%d,%d]",
				(gCodes->GetAxisIsHomed(0)) ? 1 : 0,
				(gCodes->GetAxisIsHomed(1)) ? 1 : 0,
				(gCodes->GetAxisIsHomed(2)) ? 1 : 0);
	}
	else
	{
		response->catf(",\"hx\":%d,\"hy\":%d,\"hz\":%d",
				(gCodes->GetAxisIsHomed(0)) ? 1 : 0,
				(gCodes->GetAxisIsHomed(1)) ? 1 : 0,
				(gCodes->GetAxisIsHomed(2)) ? 1 : 0);
	}

	if (printMonitor->IsPrinting())
	{
		// Send the fraction printed
		response->catf(",\"fraction_printed\":%.4f", max<float>(0.0, gCodes->FractionOfFilePrinted()));
	}

	response->cat(",\"message\":");
	response->EncodeString(message, ARRAY_SIZE(message), false);

	if (type < 2)
	{
		response->catf(",\"buff\":%u", webserver->GetGCodeBufferSpace(WebSource::HTTP));	// send the amount of buffer space available for gcodes
	}
	else if (type == 2)
	{
		if (printMonitor->IsPrinting())
		{
			// Send estimated times left based on file progress, filament usage, and layers
			response->catf(",\"timesLeft\":[%.1f,%.1f,%.1f]",
					printMonitor->EstimateTimeLeft(fileBased),
					printMonitor->EstimateTimeLeft(filamentBased),
					printMonitor->EstimateTimeLeft(layerBased));
		}
	}
	else if (type == 3)
	{
		// Add the static fields. For now this is just geometry and the machine name, but other fields could be added e.g. axis lengths.
		response->catf(",\"geometry\":\"%s\",\"myName\":", move->GetGeometryString());
		response->EncodeString(myName, ARRAY_SIZE(myName), false);
	}

	int auxSeq = (int)gCodes->GetAuxSeq();
	if (type < 2 || (seq != -1 && (int)auxSeq != seq))
	{

		// Send the response to the last command. Do this last because it can be long and may need to be truncated.
		response->catf(",\"seq\":%u,\"resp\":", auxSeq);					// send the response sequence number

		// Send the JSON response
		response->EncodeReply(gCodes->GetAuxGCodeReply(), true);			// also releases the OutputBuffer chain
	}

	response->cat("}");

	return response;
}
Exemple #29
0
// Get the JSON status response for the web server (or later for the M105 command).
// Type 1 is the ordinary JSON status response.
// Type 2 is the same except that static parameters are also included.
// Type 3 is the same but instead of static parameters we report print estimation values.
OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
{
	// Need something to write to...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		// Should never happen
		return nullptr;
	}

	// Machine status
	char ch = GetStatusCharacter();
	response->printf("{\"status\":\"%c\",\"coords\":{", ch);

	/* Coordinates */
	{
		float liveCoordinates[DRIVES + 1];
#if SUPPORT_ROLAND
		if (roland->Active())
		{
			roland->GetCurrentRolandPosition(liveCoordinates);
		}
		else
#endif
		{
			move->LiveCoordinates(liveCoordinates);
		}

		if (currentTool != nullptr)
		{
			const float *offset = currentTool->GetOffset();
			for (size_t i = 0; i < AXES; ++i)
			{
				liveCoordinates[i] += offset[i];
			}
		}

		// Homed axes
		response->catf("\"axesHomed\":[%d,%d,%d]",
				(gCodes->GetAxisIsHomed(0)) ? 1 : 0,
				(gCodes->GetAxisIsHomed(1)) ? 1 : 0,
				(gCodes->GetAxisIsHomed(2)) ? 1 : 0);

		// Actual and theoretical extruder positions since power up, last G92 or last M23
		response->catf(",\"extr\":");		// announce actual extruder positions
		ch = '[';
		for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)
		{
			response->catf("%c%.1f", ch, liveCoordinates[AXES + extruder]);
			ch = ',';
		}
		if (ch == '[')
		{
			response->cat("[");
		}

		// XYZ positions
		response->cat("],\"xyz\":");
		if (!gCodes->AllAxesAreHomed() && move->IsDeltaMode())
		{
			// If in Delta mode, skip these coordinates if some axes are not homed
			response->cat("[0.00,0.00,0.00");
		}
		else
		{
			// On Cartesian printers, the live coordinates are (usually) valid
			ch = '[';
			for (size_t axis = 0; axis < AXES; axis++)
			{
				response->catf("%c%.2f", ch, liveCoordinates[axis]);
				ch = ',';
			}
		}
	}

	// Current tool number
	int toolNumber = (currentTool == nullptr) ? -1 : currentTool->Number();
	response->catf("]},\"currentTool\":%d", toolNumber);

	/* Output - only reported once */
	{
		bool sendBeep = (beepDuration != 0 && beepFrequency != 0);
		bool sendMessage = (message[0] != 0);
		bool sourceRight = (gCodes->HaveAux() && source == ResponseSource::AUX) || (!gCodes->HaveAux() && source == ResponseSource::HTTP);
		if ((sendBeep || message[0] != 0) && sourceRight)
		{
			response->cat(",\"output\":{");

			// Report beep values
			if (sendBeep)
			{
				response->catf("\"beepDuration\":%d,\"beepFrequency\":%d", beepDuration, beepFrequency);
				if (sendMessage)
				{
					response->cat(",");
				}

				beepFrequency = beepDuration = 0;
			}

			// Report message
			if (sendMessage)
			{
				response->cat("\"message\":");
				response->EncodeString(message, ARRAY_SIZE(message), false);
				message[0] = 0;
			}
			response->cat("}");
		}
	}

	/* Parameters */
	{
		// ATX power
		response->catf(",\"params\":{\"atxPower\":%d", platform->AtxPower() ? 1 : 0);

		// Cooling fan value
		response->cat(",\"fanPercent\":[");
		for(size_t i = 0; i < NUM_FANS; i++)
		{
			if (i == NUM_FANS - 1)
			{
				response->catf("%.2f", platform->GetFanValue(i) * 100.0);
			}
			else
			{
				response->catf("%.2f,", platform->GetFanValue(i) * 100.0);
			}
		}

		// Speed and Extrusion factors
		response->catf("],\"speedFactor\":%.2f,\"extrFactors\":", gCodes->GetSpeedFactor() * 100.0);
		ch = '[';
		for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)
		{
			response->catf("%c%.2f", ch, gCodes->GetExtrusionFactor(extruder) * 100.0);
			ch = ',';
		}
		response->cat((ch == '[') ? "[]}" : "]}");
	}

	// G-code reply sequence for webserver (seqence number for AUX is handled later)
	if (source == ResponseSource::HTTP)
	{
		response->catf(",\"seq\":%d", webserver->GetReplySeq());

		// There currently appears to be no need for this one, so skip it
		//response->catf(",\"buff\":%u", webserver->GetGCodeBufferSpace(WebSource::HTTP));
	}

	/* Sensors */
	{
		response->cat(",\"sensors\":{");

		// Probe
		int v0 = platform->ZProbe();
		int v1, v2;
		switch (platform->GetZProbeSecondaryValues(v1, v2))
		{
			case 1:
				response->catf("\"probeValue\":%d,\"probeSecondary\":[%d]", v0, v1);
				break;
			case 2:
				response->catf("\"probeValue\":%d,\"probeSecondary\":[%d,%d]", v0, v1, v2);
				break;
			default:
				response->catf("\"probeValue\":%d", v0);
				break;
		}

		// Fan RPM
		response->catf(",\"fanRPM\":%d}", static_cast<unsigned int>(platform->GetFanRPM()));
	}

	/* Temperatures */
	{
		response->cat(",\"temps\":{");

		/* Bed */
		const int8_t bedHeater = heat->GetBedHeater();
		if (bedHeater != -1)
		{
			response->catf("\"bed\":{\"current\":%.1f,\"active\":%.1f,\"state\":%d},",
					heat->GetTemperature(bedHeater), heat->GetActiveTemperature(bedHeater),
					heat->GetStatus(bedHeater));
		}

		/* Chamber */
		const int8_t chamberHeater = heat->GetChamberHeater();
		if (chamberHeater != -1)
		{
			response->catf("\"chamber\":{\"current\":%.1f,", heat->GetTemperature(chamberHeater));
			response->catf("\"active\":%.1f,", heat->GetActiveTemperature(chamberHeater));
			response->catf("\"state\":%d},", static_cast<int>(heat->GetStatus(chamberHeater)));
		}

		/* Heads */
		{
			response->cat("\"heads\":{\"current\":");

			// Current temperatures
			ch = '[';
			for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%.1f", ch, heat->GetTemperature(heater));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");

			// Active temperatures
			response->catf(",\"active\":");
			ch = '[';
			for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");

			// Standby temperatures
			response->catf(",\"standby\":");
			ch = '[';
			for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");

			// Heater statuses (0=off, 1=standby, 2=active, 3=fault)
			response->cat(",\"state\":");
			ch = '[';
			for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
			{
				response->catf("%c%d", ch, static_cast<int>(heat->GetStatus(heater)));
				ch = ',';
			}
			response->cat((ch == '[') ? "[]" : "]");
		}
		response->cat("}}");
	}

	// Time since last reset
	response->catf(",\"time\":%.1f", platform->Time());

	/* Extended Status Response */
	if (type == 2)
	{
		// Cold Extrude/Retract
		response->catf(",\"coldExtrudeTemp\":%1.f", heat->ColdExtrude() ? 0 : HOT_ENOUGH_TO_EXTRUDE);
		response->catf(",\"coldRetractTemp\":%1.f", heat->ColdExtrude() ? 0 : HOT_ENOUGH_TO_RETRACT);

		// Endstops
		uint16_t endstops = 0;
		for(size_t drive = 0; drive < DRIVES; drive++)
		{
			EndStopHit stopped = platform->Stopped(drive);
			if (stopped == EndStopHit::highHit || stopped == EndStopHit::lowHit)
			{
				endstops |= (1 << drive);
			}
		}
		response->catf(",\"endstops\":%d", endstops);

		// Delta configuration
		response->catf(",\"geometry\":\"%s\"", move->GetGeometryString());

		// Machine name
		response->cat(",\"name\":");
		response->EncodeString(myName, ARRAY_SIZE(myName), false);

		/* Probe */
		{
			const ZProbeParameters probeParams = platform->GetZProbeParameters();

			// Trigger threshold
			response->catf(",\"probe\":{\"threshold\":%d", probeParams.adcValue);

			// Trigger height
			response->catf(",\"height\":%.2f", probeParams.height);

			// Type
			response->catf(",\"type\":%d}", platform->GetZProbeType());
		}

		/* Tool Mapping */
		{
			response->cat(",\"tools\":[");
			for(Tool *tool = toolList; tool != nullptr; tool = tool->Next())
			{
				// Heaters
				response->catf("{\"number\":%d,\"heaters\":[", tool->Number());
				for(size_t heater=0; heater<tool->HeaterCount(); heater++)
				{
					response->catf("%d", tool->Heater(heater));
					if (heater + 1 < tool->HeaterCount())
					{
						response->cat(",");
					}
				}

				// Extruder drives
				response->cat("],\"drives\":[");
				for(size_t drive=0; drive<tool->DriveCount(); drive++)
				{
					response->catf("%d", tool->Drive(drive));
					if (drive + 1 < tool->DriveCount())
					{
						response->cat(",");
					}
				}

				// Do we have any more tools?
				if (tool->Next() != nullptr)
				{
					response->cat("]},");
				}
				else
				{
					response->cat("]}");
				}
			}
			response->cat("]");
		}
	}
	else if (type == 3)
	{
		// Current Layer
		response->catf(",\"currentLayer\":%d", printMonitor->GetCurrentLayer());

		// Current Layer Time
		response->catf(",\"currentLayerTime\":%.1f", printMonitor->GetCurrentLayerTime());

		// Raw Extruder Positions
		response->cat(",\"extrRaw\":");
		ch = '[';
		for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)		// loop through extruders
		{
			response->catf("%c%.1f", ch, gCodes->GetRawExtruderTotalByDrive(extruder));
			ch = ',';
		}
		if (ch == '[')
		{
			response->cat("]");
		}

		// Fraction of file printed
		response->catf("],\"fractionPrinted\":%.1f", (printMonitor->IsPrinting()) ? (gCodes->FractionOfFilePrinted() * 100.0) : 0.0);

		// First Layer Duration
		response->catf(",\"firstLayerDuration\":%.1f", printMonitor->GetFirstLayerDuration());

		// First Layer Height
		// NB: This shouldn't be needed any more, but leave it here for the case that the file-based first-layer detection fails
		response->catf(",\"firstLayerHeight\":%.2f", printMonitor->GetFirstLayerHeight());

		// Print Duration
		response->catf(",\"printDuration\":%.1f", printMonitor->GetPrintDuration());

		// Warm-Up Time
		response->catf(",\"warmUpDuration\":%.1f", printMonitor->GetWarmUpDuration());

		/* Print Time Estimations */
		{
			// Based on file progress
			response->catf(",\"timesLeft\":{\"file\":%.1f", printMonitor->EstimateTimeLeft(fileBased));

			// Based on filament usage
			response->catf(",\"filament\":%.1f", printMonitor->EstimateTimeLeft(filamentBased));

			// Based on layers
			response->catf(",\"layer\":%.1f}", printMonitor->EstimateTimeLeft(layerBased));
		}
	}

	if (source == ResponseSource::AUX)
	{
		OutputBuffer *response = gCodes->GetAuxGCodeReply();
		if (response != nullptr)
		{
			// Send the response to the last command. Do this last
			response->catf(",\"seq\":%u,\"resp\":", gCodes->GetAuxSeq());			// send the response sequence number

			// Send the JSON response
			response->EncodeReply(response, true);									// also releases the OutputBuffer chain
		}
	}
	response->cat("}");

	return response;
}
Exemple #30
0
OutputBuffer *RepRap::GetConfigResponse()
{
	// We need some resources to return a valid config response...
	OutputBuffer *response;
	if (!OutputBuffer::Allocate(response))
	{
		return nullptr;
	}

	// Axis minima
	response->copy("{\"axisMins\":");
	char ch = '[';
	for (size_t axis = 0; axis < AXES; axis++)
	{
		response->catf("%c%.2f", ch, platform->AxisMinimum(axis));
		ch = ',';
	}

	// Axis maxima
	response->cat("],\"axisMaxes\":");
	ch = '[';
	for (size_t axis = 0; axis < AXES; axis++)
	{
		response->catf("%c%.2f", ch, platform->AxisMaximum(axis));
		ch = ',';
	}

	// Accelerations
	response->cat("],\"accelerations\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->Acceleration(drive));
		ch = ',';
	}

	// Motor currents
	response->cat("],\"currents\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->MotorCurrent(drive));
		ch = ',';
	}

	// Firmware details
	response->catf("],\"firmwareElectronics\":\"%s\"", ELECTRONICS);
	response->catf(",\"firmwareName\":\"%s\"", NAME);
	response->catf(",\"firmwareVersion\":\"%s\"", VERSION);
	response->catf(",\"firmwareDate\":\"%s\"", DATE);

	// Motor idle parameters
	response->catf(",\"idleCurrentFactor\":%.1f", platform->GetIdleCurrentFactor() * 100.0);
	response->catf(",\"idleTimeout\":%.1f", move->IdleTimeout());

	// Minimum feedrates
	response->cat(",\"minFeedrates\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->ConfiguredInstantDv(drive));
		ch = ',';
	}

	// Maximum feedrates
	response->cat("],\"maxFeedrates\":");
	ch = '[';
	for (size_t drive = 0; drive < DRIVES; drive++)
	{
		response->catf("%c%.2f", ch, platform->MaxFeedrate(drive));
		ch = ',';
	}

	// Configuration File (whitespaces are skipped, otherwise we easily risk overflowing the response buffer)
	response->cat("],\"configFile\":\"");
	FileStore *configFile = platform->GetFileStore(platform->GetSysDir(), platform->GetConfigFile(), false);
	if (configFile == nullptr)
	{
		response->cat("not found");
	}
	else
	{
		char c, esc;
		bool readingWhitespace = false;
		size_t bytesWritten = 0, bytesLeft = OutputBuffer::GetBytesLeft(response);
		while (configFile->Read(c) && bytesWritten + 4 < bytesLeft)		// need 4 bytes to finish this response
		{
			if (!readingWhitespace || (c != ' ' && c != '\t'))
			{
				switch (c)
				{
					case '\r':
						esc = 'r';
						break;
					case '\n':
						esc = 'n';
						break;
					case '\t':
						esc = 't';
						break;
					case '"':
						esc = '"';
						break;
					case '\\':
						esc = '\\';
						break;
					default:
						esc = 0;
						break;
				}

				if (esc)
				{
					response->catf("\\%c", esc);
					bytesWritten += 2;
				}
				else
				{
					response->cat(c);
					bytesWritten++;
				}
			}
			readingWhitespace = (c == ' ' || c == '\t');
		}
		configFile->Close();
	}
	response->cat("\"}");

	return response;
}