/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package project.latex.balloon.writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
/**
*
* @author dgorst
*/
public class ChunkedSerialDataWriter implements DataWriter {
private static final Logger logger = Logger.getLogger(ChunkedSerialDataWriter.class);
// Size of data chunks in bytes.
private final int chunkSize = 16;
private final int delayInMilliseconds;
private final SerialDataWriter dataWriter;
private final List<String> chunks;
private final Thread worker;
public ChunkedSerialDataWriter(int baudRate, SerialDataWriter dataWriter) {
this.chunks = new ArrayList<>();
final int byteSize = 8;
// This provides some allowance for the time that there is no data being sent
// due to the software being on another thread etc.. gives some margin of error.
final double extraDelayMultiplier = 1.1;
this.delayInMilliseconds = (int) ((chunkSize * byteSize/baudRate) * 1000 * extraDelayMultiplier);
this.dataWriter = dataWriter;
worker = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
// Write the next chunk of data if it is available
writeNextChunk();
try {
// Wait for the specified delay before writing the next chunk
Thread.sleep(delayInMilliseconds);
} catch (InterruptedException ex) {
logger.error(ex.getMessage(), ex);
}
}
}
});
}
public List<String> getChunks() {
return chunks;
}
public void start() {
logger.info("Chunked serial data writer started");
worker.start();
}
synchronized void addChunk(String chunk) {
this.chunks.add(chunk);
}
synchronized void writeNextChunk() {
if (!this.chunks.isEmpty()) {
String chunk = this.chunks.remove(0);
logger.info("Next chunk to write: " + chunk);
this.dataWriter.writeString(chunk);
}
}
List<String> breakDataIntoChunks(String data) {
List<String> chunkedData = new ArrayList<>();
for (int i = 0; i < data.length(); i += chunkSize) {
int endIndex = Math.min(data.length(), i + chunkSize);
chunkedData.add(data.substring(i, endIndex));
}
return chunkedData;
}
@Override
public void writeData(Map<String, Object> dataModel) {
String csvString = this.dataWriter.convertDataToCsvString(dataModel);
logger.info(csvString);
// Add a new line character to the start and end of our data so that we can separate sentences
csvString = "\n" + csvString + "\n";
// Break our data into chunks to pass to our serial data writer
List<String> newChunks = breakDataIntoChunks(csvString);
// Add the chunks to our collection
for (String chunk : newChunks) {
addChunk(chunk);
}
}
}