Read multiple characteristics from an Android device using library RxAndroidBle - bluetooth-lowenergy

I am using the library RxAndroidBle in order to scan devices and then connect to one specific device and read 4 GATT characteristics.
I can read one characteristic (Battery Level) ith this code :
scanSubscription = rxBleClient.scanBleDevices(
new ScanSettings.Builder()
.build()
)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(
scanResult -> {
if(scanResult.getBleDevice().getName() != null){
if(scanResult.getBleDevice().getName().equals("NODE 1")){
Log.e("BLE SCAN", "SUCCESS");
Log.e("BLE SCAN", scanResult.getBleDevice().getName());
Log.e("BLE SCAN", scanResult.getBleDevice().getMacAddress());
scanSubscription.unsubscribe();
RxBleDevice device = scanResult.getBleDevice();
subscription = device.establishConnection(false) // <-- autoConnect flag
.flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")))
.subscribe(
characteristicValue -> {
Log.e("Characteristic", characteristicValue[0]+"");
},
throwable -> {
Log.e("Error", throwable.getMessage());
}
);
}
}
}
)
.subscribe();
I can read two by using :
.flatMap(rxBleConnection -> Observable.combineLatest( // use the same connection and combine latest emissions
rxBleConnection.readCharacteristic(aUUID),
rxBleConnection.readCharacteristic(bUUID),
Pair::new
))
But I don't understand how to do that with 4 characteristics for example.
Thank you

The above example is just fine you would only need some data object that would accept more values than Pair. For instance something like:
class ReadResult {
final byte[] aValue;
final byte[] bValue;
final byte[] cValue;
final byte[] dValue;
ReadResult(byte[] aValue, byte[] bValue, byte[] cValue, byte[] dValue) {
this.aValue = aValue;
this.bValue = bValue;
this.cValue = cValue;
this.dValue = dValue;
}
}
And then the example could look like this:
disposable = rxBleClient.scanBleDevices(
new ScanSettings.Builder().build(),
new ScanFilter.Builder().setDeviceName("NODE 1").build() // one can set filtering by name here
)
.take(1) // take only the first result and then the upstream will get unsubscribed (scan will end)
.flatMap(scanResult -> scanResult.getBleDevice().establishConnection(false)) // connect to the first scanned device that matches the filter
.flatMapSingle(rxBleConnection -> Single.zip( // once connected read all needed values
rxBleConnection.readCharacteristic(aUUID),
rxBleConnection.readCharacteristic(bUUID),
rxBleConnection.readCharacteristic(cUUID),
rxBleConnection.readCharacteristic(dUUID),
ReadResult::new // merge them into a single result
))
.take(1) // once the result of all reads is available unsubscribe from the upstream (connection will end)
.subscribe(
readResult -> Log.d("Characteristics", /* print the readResult */),
throwable -> Log.e("Error", throwable.getMessage())
);
Original/Legacy solution for RxAndroidBle based on RxJava1:
subscription = rxBleClient.scanBleDevices(
new ScanSettings.Builder().build(),
new ScanFilter.Builder().setDeviceName("NODE 1").build() // one can set filtering by name here
)
.take(1) // take only the first result and then the upstream will get unsubscribed (scan will end)
.flatMap(scanResult -> scanResult.getBleDevice().establishConnection(false)) // connect to the first scanned device that matches the filter
.flatMap(rxBleConnection -> Observable.combineLatest( // once connected read all needed values
rxBleConnection.readCharacteristic(aUUID),
rxBleConnection.readCharacteristic(bUUID),
rxBleConnection.readCharacteristic(cUUID),
rxBleConnection.readCharacteristic(dUUID),
ReadResult::new // merge them into a single result
))
.take(1) // once the result of all reads is available unsubscribe from the upstream (connection will end)
.subscribe(
readResult -> Log.d("Characteristics", /* print the readResult */),
throwable -> Log.e("Error", throwable.getMessage())
);

Related

Spring-integration SFTP file handling one-by-one and exception handling

#Bean
public IntegrationFlow acknowledgeFileFlows() {
return f -> f
.enrichHeaders(h -> h
.headerExpression("originalPayload", "payload.toString()")
.headerExpression(FileHeaders.REMOTE_DIRECTORY, "payload.toString()"))
.log(LoggingHandler.Level.INFO, "eu.xxx", "'acknowledgeFileFlows Header originalPayload=' + headers[originalPayload]")
.handle(Sftp.outboundGateway(sessionFactory, Command.LS.getCommand(), "payload")
.autoCreateDirectory(false)
.autoCreateLocalDirectory(false)
.charset("UTF-8")
.regexFileNameFilter("(?i)(FileAcK_CITI_PMT[a-zA-Z0-9_.-]+|TxnAck_CITI_PMT[a-zA-Z0-9_.-]+|TxnNak_CITI_PMT[a-zA-Z0-9_.-]+)")
.options(Option.NAME_ONLY, Option.RECURSIVE))
.split()
.log(LoggingHandler.Level.INFO, "eu.xxx", "'acknowledgeFileFlows LS Payload= ' + payload.toString()")
.enrichHeaders(h -> h
.headerExpression("startTime", "new java.util.Date()")
.headerExpression("originalRemoteFile", "payload.toString()")
.headerExpression(FileHeaders.REMOTE_FILE, "payload.toString()"))
.handle(Sftp.outboundGateway(sessionFactory, Command.GET.getCommand(), "headers['originalPayload'] + headers['file_remoteFile']")
.autoCreateLocalDirectory(false)
.charset("UTF-8")
.fileExistsMode(FileExistsMode.REPLACE)
.fileNameExpression("headers['file_remoteFile']")
.localDirectoryExpression(new FunctionExpression<Message<?>>(m -> {
IntegrationMessageHeaderAccessor accessor = new IntegrationMessageHeaderAccessor(m);
final String remoteFileName = (String) accessor.getHeader("file_remoteFile");
final String ackFileRootPath = applicationConfiguration.getAcknowledgeFileTargetUri();
if (remoteFileName.toUpperCase().contains("XXX")) {
return Paths.get(ackFileRootPath, "XXX", RCIV, ACK).toString();
} else if (remoteFileName.toUpperCase().contains("YYY")) {
return Paths.get(ackFileRootPath, "YYY", RCIV, ACK).toString();
} else {
String[] parts = remoteFileName.toUpperCase().split("ZZZ");
if (parts != null && parts.length >= 2) {
return Paths.get(ackFileRootPath, "ZZZ", RCIV, ACK).toString();
}
}
return ackFileRootPath;
}))
.localFilenameExpression("headers['file_remoteFile']")
.options(Option.PRESERVE_TIMESTAMP)
.remoteFileSeparator("/"))
.handle((payload, headers) -> {
File file = (File) payload;
file.setWritable(true, false);
file.setReadable(true, false);
return file;
})
.enrichHeaders(h -> h
.headerExpression("fileLength", "payload.length")
.headerExpression("localDirectory", "payload.toString()"))
.wireTap(w -> w
.handle((payload, headers) -> {
return transactionLog("XXX_TR_ACK_FILE",
(Date) headers.get("startTime"),
(String) headers.get("localDirectory"),
(String) headers.get("file_remoteFile"),
headers.get("fileLength"));
})
.handle(Jpa.outboundAdapter(sourceIntegrationEntityManagerFactory)
.entityClass(TranComLog.class)
.persistMode(PersistMode.PERSIST), e -> e.transactional()))
.aggregate()
.channel(new NullChannel());
}
Above is the file download flows configuration.
This flow takes the remote SFTP path as the initial parameter.
LS -> File name process to get the correct target folder -> GET -> Write some log in to the DB.
The remote SFTP path can contain multiple files. I have to process those files one by one due to the requirement. (That's why I added the split)
My issue is when any exception occurs this flow stopped. I have to restart the server.
I think the reason is there is no correct exception handling in my flow, especially between the split and aggregate.
Does the Sftp.outboundGateway process the files one by one? If yes, the split and aggregate can be removed. Am I right?
If not, should I keep the split and aggregate? how can I add the proper exception handling?

Reactive Kafka Receiver poll new records even old ones are not ack

I am trying to use Reactive Kafka Receiver in order to process Kafka messages. I expected that consumer will give me new message only in case the last one I polled has been acknowledged. However, even if I do not run ack I get new records. Is it a desired behaviour or am I missing some configs?
void consumeMessages() {
kafkaConsumer(() -> true).subscribe();
}
Flux<Void> kafkaConsumer(BooleanSupplier repeatCondition) {
return reactiveConsumer
.receive()
.doOnError(error -> log.warn("Received error when get kafka message", error))
.doOnNext(receivedRecord -> log.debug("Received event {}", receivedRecord.value()))
.flatMap(this::handleReceivedRecord)
.onErrorResume(error -> Flux.empty())
.repeat(repeatCondition);
}
Flux<Void> handleReceivedRecord(ReceiverRecord<String, CustomEvent> receivedRecord) {
return Mono.just(receivedRecord)
.flatMapMany(
record ->
handleCustomEvent(record.value())
.doOnComplete(() -> {
log.debug("Committing offset for record: {}", record);
//record.receiverOffset().acknowledge();
})
.onErrorMap(error -> new ReceiverRecordException(record, error)))
.doOnError(error -> log.error("Error when processing CustomEvent", error))
.retryWhen(
Retry.backoff(consumerProperties.retries(), consumerProperties.minBackOff())
.transientErrors(true))
.onErrorResume(
error -> {
ReceiverRecordException ex = (ReceiverRecordException) error.getCause();
log.warn("Retries exhausted for " + ex.getRecord().value());
ex.getRecord().receiverOffset().acknowledge();
return Mono.empty();
});
}

InputStream never calls hasBytesAvailable

I'm trying to get iOS devices to discover each other with Bonjour and then connect with InputStream and OutputStream.
The devices can connect to each other, but sending bytes from one device's OutputStream will not trigger the "hasBytesAvailable" event on the other device.
Because I want devices to connect with multiple other devices, I've wrapped each connection in an "ASPeer" object, which I can put in an array to keep track of all my connections.
class ASPeer: NSObject {
let service: NetService
var inputStream: InputStream?
var outputStream: OutputStream?
init(_ service: NetService) {
self.service = service
}
func openStreams() {
guard let inputStream = inputStream, let outputStream = outputStream else {
fatalError("openStreams: failed to get streams!")
}
inputStream.delegate = self
inputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
inputStream.open()
outputStream.delegate = self
outputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
outputStream.open()
}
func closeStreams() {
guard let inputStream = inputStream, let outputStream = outputStream else {
fatalError("closeStreams: failed to get streams!")
}
inputStream.remove(from: .current, forMode: .defaultRunLoopMode)
inputStream.close()
inputStream.delegate = nil
outputStream.remove(from: .current, forMode: .defaultRunLoopMode)
outputStream.close()
outputStream.delegate = nil
}
}
extension ASPeer: StreamDelegate {
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
switch aStream {
case inputStream!:
switch eventCode {
case .openCompleted:
print("inputOpenCompleted:")
case .hasBytesAvailable:
print("inputHasBytesAvailable:")
var readData = [UInt8](Data(capacity: 4096))
let bytesRead = inputStream!.read(&readData, maxLength: 4096)
if bytesRead > 0 {
print(String(bytes: readData, encoding: .ascii)!)
}
case .errorOccurred:
print("inputErrorOccurred")
case .endEncountered:
print("inputEndEncountered")
default:
break
}
case outputStream!:
switch eventCode {
case .openCompleted:
print("outputOpenCompleted:")
case .hasSpaceAvailable:
print("outputHasSpaceAvailable:")
case .errorOccurred:
print("outputErrorOccurred")
case .endEncountered:
print("outputEndEncountered")
default:
break
}
default:
print("got unknown stream!")
}
}
}
I've added print statements to every single "handle" event for my input and output streams. Here are the output logs when I run the app and try to get the devices to talk to each other:
Device 1
inputOpenCompleted:
outputOpenCompleted:
outputHasSpaceAvailable:
Device 2
inputOpenCompleted:
outputOpenCompleted:
outputHasSpaceAvailable:
When I try to send a message from Device 1 to Device 2, I'm expecting Device 2 to print out "inputHasBytesAvailable". However, I just get extra lines of "outputHasSpaceAvailable" from Device 1:
Device 1
inputOpenCompleted:
outputOpenCompleted:
outputHasSpaceAvailable:
outputHasSpaceAvailable: <--
outputHasSpaceAvailable: <--
Device 2
inputOpenCompleted:
outputOpenCompleted:
outputHasSpaceAvailable:
<-- I'm expecting "inputHasBytesAvailable" here!
What could the issue be? I've double checked my run loops and made sure they are correct. Also, there seems to be a bug with "getInputStream" and I made sure to call "getInputStream" on the main queue to avoid that problem. Is there something else I'm missing?
In addition, I also have a BonjourManager object that manages every one of these "ASPeer" connections. The BonjourManager is what actually creates the connections and sends writes to the OutputStreams.
class ASBonjourManager: NetServiceDelegate {
var peers = [ASPeer]()
// ... more code here but omitted
func netService(_ sender: NetService, didAcceptConnectionWith inputStream: InputStream, outputStream: OutputStream) {
if sender == advertiser {
return
}
if let peer = peers.first(where: { $0.service == sender }) {
OperationQueue.main.addOperation {
// Due to a bug <rdar://problem/15626440>, this method is called on some unspecified
// queue rather than the queue associated with the net service (which in this case
// is the main queue). Work around this by bouncing to the main queue.
assert((peer.inputStream == nil) == (peer.outputStream == nil))
if let _ = peer.inputStream, let _ = peer.outputStream {
inputStream.open()
inputStream.close()
outputStream.open()
outputStream.close()
} else {
peer.inputStream = inputStream
peer.outputStream = outputStream
peer.openStreams()
}
}
} else {
OperationQueue.main.addOperation {
let newPeer = ASPeer(sender)
sender.delegate = self
newPeer.inputStream = inputStream
newPeer.outputStream = outputStream
newPeer.openStreams()
self.peers.append(newPeer)
}
}
}
func connectTo(service: NetService) {
var inStream: InputStream?
var outStream: OutputStream?
let peer = peers.first(where: { $0.service.isEqual(service) })!
//assert(peer.inputStream == nil && peer.outputStream == nil)
if peer.inputStream != nil && peer.outputStream != nil {
return
}
if service.getInputStream(&inStream, outputStream: &outStream) {
peer.inputStream = inStream
peer.outputStream = outStream
peer.openStreams()
} else {
print("getInputStream failed!")
}
}
func sendMessage(_ service: NetService) {
let peer = peers.first(where: { $0.service.isEqual(service) })!
if peer.outputStream!.hasSpaceAvailable {
let message = Array("hello world".utf8)
peer.outputStream!.write(message, maxLength: message.count)
}
}
}

Serial Connection (Arduino --> Java)

this will be my first post and I will do my best to be clear and concise. I've checked some of the other posts on this forum but was unable to find a satisfactory answer.
My question pertains to the use of JavaFX and the jSSC(java simple serial connection) library. I've designed a very simple GUI application that will host four different charts. Two of the charts will display readings from temperature and solar sensors for the past hour, while the other two display that data over an extended period -- a 14-hour period. Eventually I would like to make that more flexible and set the application to "sleep" when the readings become roughly zero (night).
How can I stream data to display this data in real time?
After referencing several sources online and from "JavaFX 8 Intro. by Example", I've been able to construct most of the serial connection class. I'm having trouble processing the data readings, so that it can be displayed on the chart.
public class SerialComm implements SerialPortEventListener {
Date time = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("mm");
boolean connected;
StringBuilder sb;
private SerialPort serialPort;
final StringProperty line = new SimpleStringProperty("");
//Not sure this is necessary
private static final String [] PORT_NAMES = {
"/dev/tty.usbmodem1411", // Mac OS X
"COM11", // Windows
};
//Baud rate of communication transfer with serial device
public static final int DATA_RATE = 9600;
//Create a connection with the serial device
public boolean connect() {
String [] ports = SerialPortList.getPortNames();
//First, Find an instance of serial port as set in PORT_NAMES.
for (String port : ports) {
System.out.print("Ports: " + port);
serialPort = new SerialPort(port);
}
if (serialPort == null) {
System.out.println("Could not find device.");
return false;
}
//Operation to perform is port is found
try {
// open serial port
if(serialPort.openPort()) {
System.out.println("Connected");
// set port parameters
serialPort.setParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
serialPort.setEventsMask(SerialPort.MASK_RXCHAR);
serialPort.addEventListener(event -> {
if(event.isRXCHAR()) {
try {
sb.append(serialPort.readString(event.getEventValue()));
String str = sb.toString();
if(str.endsWith("\r\n")) {
line.set(Long.toString(time.getTime()).concat(":").concat(
str.substring(0, str.indexOf("\r\n"))));
System.out.println("line" + line);
sb = new StringBuilder();
}
} catch (SerialPortException ex) {
Logger.getLogger(SerialComm.class.getName()).log(Level.SEVERE, null, ex); }
}
});
}
} catch (Exception e) {
System.out.println("ErrOr");
e.printStackTrace();
System.err.println(e.toString());
}
return serialPort != null;
}
#Override
public void serialEvent(SerialPortEvent spe) {
throw new UnsupportedOperationException("Not supported yet.");
}
public StringProperty getLine() {
return line;
}
}
Within the try block, I understand the port parameters, but the eventListener is where I am having difficulty. The significance of the stringbuilder is to append data the new data as it is read from the device.
How will I account for the two sensor readings? Would I do that by creating separate data rates to differentiate between the incoming data from each sensor??
I hope that this is clear and that I've provided enough information but not too much. Thank you for any assistance.
-------------------------------UPDATE--------------------------
Since your reply Jose, I've started to make the additions to my code. Adding the listener within the JavaFX class, I'm running into some issues. I keep getting a NullPointerException, which I believe is the String[]data not being initialized by any data from the SerialCommunication class.
serialPort.addEventListener(event -> {
if(event.isRXCHAR()) {
try {
sb.append(serialPort.readString(event.getEventValue()));
String str = sb.toString();
if(str.endsWith("\r\n")) {
line.set(Long.toString(time.getTime()).concat(":").concat(
str.substring(0, str.indexOf("\r\n"))));
System.out.println("line" + line);
sb = new StringBuilder();
}
} catch (SerialPortException ex) {
Logger.getLogger(SerialComm.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
} catch (Exception e) {
System.err.println(e.toString());
}
I'm adding the time to the data being read. As Jose mentioned below, I've added tags to the data variables within the arduino code, I'm using: Serial.print("Solar:"); Serial.println(solarData);
Rough code of the JavaFx listener:
serialPort.getLine().addListener((ov, t, t1) -> {
Platform.runLater(()-> {
String [] data = t1.split(":");
try {
//data[0] is the timestamp
//data[1] will contain the label printed by arduino "Solar: data"
switch (data[1]) {
case "Solar":
data[0].replace("Solar:" , "");
solarSeries.getData().add(new XYChart.Data(data[0], data[1]));
break;
case "Temperature":
temperatureSeries.getData().add(new XYChart.Data(data[0], data[1]));
break;
}
Is the reason this code has NullPointerException a result of the String [] data array being uninitialized?
Exception Error
Ports: /dev/tty.usbmodem1411Connected
Exception in thread "EventThread /dev/tty.usbmodem1411" java.lang.NullPointerException
at SerialComm.lambda$connect$0(SerialComm.java:61)
at SerialComm$$Lambda$1/1661773475.serialEvent(Unknown Source)
at jssc.SerialPort$LinuxEventThread.run(SerialPort.java:1299)
The SerialPortEventListener defined in the jssc library allows listening for serial port events. One of those events is the RXCHAR event, that occurs when the Arduino board is sending some data and some bytes are on the input buffer.
event.getEventValue() returns an int with the byte count, and serialPort.readString(event.getEventValue()) get the String format from those bytes.
Note that this method does not return a full line, so you need to listen to carriage return and line feed characters. Once you find "\r\n", you can get the line, and reset the StringBuilder for the next one:
sb.append(serialPort.readString(event.getEventValue()));
String str=sb.toString();
if(str.endsWith("\r\n")){
line.set(str.substring(0,str.indexOf("\r\n")));
sb=new StringBuilder();
}
where line is an observable String:
final StringProperty line=new SimpleStringProperty("");
On the Arduino side, if you want to send values from different sensors at different rates, I suggest you define on the Arduino sketch some identification string for each sensor, and you print for each value the id of its sensor.
For instance, these will be the readings you will get with the serial event listener:
ID1,val1
ID1,val2
ID2,val3
ID1,val4
ID3,val5
...
Finally, on the JavaFX thread, define a listener to changes in line and process the String to get the sensor and the value. Something like this:
serial.getLine().addListener(
(ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
Platform.runLater(()->{
String[] data=newValue.split("\\,");
if(data[0].equals("ID1"){
// add to chart from sensor 1, value data[1];
} else if(data[0].equals("ID2"){
// add to chart from sensor 2, value data[1];
} else if(data[0].equals("ID3"){
// add to chart from sensor 3, value data[1];
}
});
});
Note you need to add Platform.runLater(), since the thread that gets the data from serial port and updates line is not on the JavaFX thread.
From my experience, on the Arduino side, add a comma or something to separate the different values when you print and when you receive that string in Java simply split that string by commas.
String[] stringSeparate = str.split(",");

LwIP Netconn API + FreeRTOS TCP Client Buffer Issue

I've been trying to modify the tcp server example with LwIP in STM32F4DISCOVERY board. I have to write a sender which does not necessarily have to reply server responses. It can send data with 100 ms frequency, for example.
Firstly, the example of TCP server is like this:
static void tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
LWIP_UNUSED_ARG(arg);
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL) {
/* Bind connection to well known port number 7. */
err = netconn_bind(conn, NULL, DEST_PORT);
if (err == ERR_OK) {
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while (1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/* Process the new connection. */
if (newconn) {
struct netbuf *buf;
void *data;
u16_t len;
while ((buf = netconn_recv(newconn)) != NULL) {
do {
netbuf_data(buf, &data, &len);
//Incoming package
.....
//Check for data
if (DATA IS CORRECT)
{
//Reply
data = "OK";
len = 2;
netconn_write(newconn, data, len, NETCONN_COPY);
}
} while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/* Close connection and discard connection identifier. */
netconn_close(newconn);
netconn_delete(newconn);
}
}
} else {
printf(" can not bind TCP netconn");
}
} else {
printf("can not create TCP netconn");
}
}
I modified this code to obtain a client version, this is what I've got so far:
static void tcpecho_thread(void *arg)
{
struct netconn *xNetConn = NULL;
struct ip_addr local_ip;
struct ip_addr remote_ip;
int rc1, rc2;
struct netbuf *Gonderilen_Buf = NULL;
struct netbuf *gonderilen_buf = NULL;
void *b_data;
u16_t b_len;
IP4_ADDR( &local_ip, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3 );
IP4_ADDR( &remote_ip, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
xNetConn = netconn_new ( NETCONN_TCP );
rc1 = netconn_bind ( xNetConn, &local_ip, DEST_PORT );
rc2 = netconn_connect ( xNetConn, &remote_ip, DEST_PORT );
b_data = "+24C"; // Data to be send
b_len = sizeof ( b_data );
while(1)
{
if ( rc1 == ERR_OK )
{
// If button pressed, send data "+24C" to server
if (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET)
{
Buf = netbuf_new();
netbuf_alloc(Buf, 4); // 4 bytes of buffer
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
vTaskDelay(100); // To see the result easily in Comm Operator
netbuf_delete(Buf);
}
}
if ( rc1 != ERR_OK || rc2 != ERR_OK )
{
netconn_delete ( xNetConn );
}
}
}
While the writing operation works, netconn_write sends what's on its buffer. It doesnt care whether b_data is NULL or not. I've tested it by adding the line b_data = NULL;
So the resulting output in Comm Operator is like this:
Rec:(02:47:27)+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C
However, I want it to work like this:
Rec:(02:47:22)+24C
Rec:(02:47:27)+24C
Rec:(02:57:12)+24C
Rec:(02:58:41)+24C
The desired write operation happens when I wait for around 8 seconds before I push the button again.
Since netconn_write function does not allow writing to a buffer, I'm not able to clear it. And netconn_send is only allowed for UDP connections.
I need some guidance to understand the problem and to generate a solution for it.
Any help will be greately appreciated.
It's just a matter of printing the result in the correct way.
You can try to add this part of code before writing in the netbuf data structure:
char buffer[20];
sprintf(buffer,"24+ \n");
Buf->p->payload = "+24C";
I see one or two problems in your code, depending on what you want it exactly to do. First of all, you're not sending b_data at all, but a constant string:
b_data = "+24C"; // Data to be send
and then
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
b_data is not anywhere mentioned there. What is sent is the payload. Try Buf->p->payload = b_data; if it's what you want to achieve.
Second, if you want the +24C text to be sent only once when you push the button, you'll have to have a loop to wait for the button to open again before continuing the loop, or it will send +24C continuously until you stop pushing the button. Something in this direction:
while (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET) {
vTaskDelay(1);
}

Resources