Extended mbus_recv_frame() error codes, improved collision handling
- handling TCP connection reset and read(2) timeout
This commit is contained in:
parent
82aec2ff97
commit
5d079254cc
2
bin/mbus-serial-request-data.c
Normal file → Executable file
2
bin/mbus-serial-request-data.c
Normal file → Executable file
@ -126,7 +126,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (mbus_recv_frame(handle, &reply) == -1)
|
||||
if (mbus_recv_frame(handle, &reply) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to receive M-Bus response frame.\n");
|
||||
return 1;
|
||||
|
13
bin/mbus-serial-scan.c
Normal file → Executable file
13
bin/mbus-serial-scan.c
Normal file → Executable file
@ -97,7 +97,7 @@ main(int argc, char **argv)
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -108,22 +108,15 @@ main(int argc, char **argv)
|
||||
if (ret == -2)
|
||||
{
|
||||
/* check for more data (collision) */
|
||||
while (mbus_recv_frame(handle, &reply) != -1);
|
||||
|
||||
mbus_recv_frame_dummy(handle);
|
||||
printf("Collision at address %d\n", address);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
|
||||
{
|
||||
/* check for more data (collision) */
|
||||
while (mbus_recv_frame(handle, &reply) != -1)
|
||||
{
|
||||
ret = -2;
|
||||
}
|
||||
|
||||
if (ret == -2)
|
||||
if (mbus_recv_frame_dummy(handle))
|
||||
{
|
||||
printf("Collision at address %d\n", address);
|
||||
|
||||
|
4
bin/mbus-serial-select-secondary.c
Normal file → Executable file
4
bin/mbus-serial-select-secondary.c
Normal file → Executable file
@ -73,7 +73,7 @@ main(int argc, char **argv)
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
printf("No reply from device with secondary address %s: %s\n", argv[2], mbus_error_str());
|
||||
return 1;
|
||||
@ -93,7 +93,7 @@ main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mbus_recv_frame(handle, &reply) == -1)
|
||||
if (mbus_recv_frame(handle, &reply) != 0)
|
||||
{
|
||||
printf("Failed to recieve reply from selected secondary device: %s\n", mbus_error_str());
|
||||
return 1;
|
||||
|
2
bin/mbus-serial-switch-baudrate.c
Normal file → Executable file
2
bin/mbus-serial-switch-baudrate.c
Normal file → Executable file
@ -72,7 +72,7 @@ main(int argc, char **argv)
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
printf("No reply from device\n");
|
||||
return 1;
|
||||
|
6
bin/mbus-tcp-request-data.c
Normal file → Executable file
6
bin/mbus-tcp-request-data.c
Normal file → Executable file
@ -111,11 +111,11 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (mbus_recv_frame(handle, &reply) == -1)
|
||||
if (mbus_recv_frame(handle, &reply) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to receive M-Bus response frame.\n");
|
||||
fprintf(stderr, "Failed to receive M-Bus response frame: %s\n", mbus_error_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// parse data and print in XML format
|
||||
|
17
bin/mbus-tcp-scan.c
Normal file → Executable file
17
bin/mbus-tcp-scan.c
Normal file → Executable file
@ -17,7 +17,6 @@
|
||||
#include <stdio.h>
|
||||
#include <mbus/mbus.h>
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Execution starts here:
|
||||
//------------------------------------------------------------------------------
|
||||
@ -81,7 +80,7 @@ main(int argc, char **argv)
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -92,28 +91,20 @@ main(int argc, char **argv)
|
||||
if (ret == -2)
|
||||
{
|
||||
/* check for more data (collision) */
|
||||
while (mbus_recv_frame(handle, &reply) != -1);
|
||||
|
||||
mbus_recv_frame_dummy(handle);
|
||||
printf("Collision at address %d\n", address);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
|
||||
{
|
||||
/* check for more data (collision) */
|
||||
while (mbus_recv_frame(handle, &reply) != -1)
|
||||
{
|
||||
ret = -2;
|
||||
}
|
||||
|
||||
if (ret == -2)
|
||||
if (mbus_recv_frame_dummy(handle))
|
||||
{
|
||||
printf("Collision at address %d\n", address);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
printf("Found a M-Bus device at address %d\n", address);
|
||||
}
|
||||
}
|
||||
|
4
bin/mbus-tcp-select-secondary.c
Normal file → Executable file
4
bin/mbus-tcp-select-secondary.c
Normal file → Executable file
@ -59,7 +59,7 @@ main(int argc, char **argv)
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
printf("No reply from device with secondary address %s: %s\n", argv[3], mbus_error_str());
|
||||
return 1;
|
||||
@ -79,7 +79,7 @@ main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mbus_recv_frame(handle, &reply) == -1)
|
||||
if (mbus_recv_frame(handle, &reply) != 0)
|
||||
{
|
||||
printf("Failed to recieve reply from selected secondary device: %s\n", mbus_error_str());
|
||||
return 1;
|
||||
|
36
mbus/mbus-protocol-aux.c
Normal file → Executable file
36
mbus/mbus-protocol-aux.c
Normal file → Executable file
@ -1407,6 +1407,24 @@ mbus_recv_frame(mbus_handle * handle, mbus_frame *frame)
|
||||
return result;
|
||||
}
|
||||
|
||||
int mbus_recv_frame_dummy(mbus_handle *handle)
|
||||
{
|
||||
int err, received;
|
||||
mbus_frame reply;
|
||||
|
||||
received = 0;
|
||||
while (1)
|
||||
{
|
||||
err = mbus_recv_frame(handle, &reply);
|
||||
if (err != -2 && err != 0)
|
||||
break;
|
||||
|
||||
received = 1;
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
int
|
||||
mbus_send_frame(mbus_handle * handle, mbus_frame *frame)
|
||||
{
|
||||
@ -1601,7 +1619,7 @@ mbus_sendrecv_request(mbus_handle *handle, int address, mbus_frame *reply, int m
|
||||
if (debug)
|
||||
printf("%s: debug: receiving response frame #%d\n", __PRETTY_FUNCTION__, frame_count);
|
||||
|
||||
if (mbus_recv_frame(handle, next_frame) == -1)
|
||||
if (mbus_recv_frame(handle, next_frame) != 0)
|
||||
{
|
||||
MBUS_ERROR("%s: Failed to receive M-Bus response frame.\n", __PRETTY_FUNCTION__);
|
||||
retval = 1;
|
||||
@ -1743,7 +1761,7 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
return MBUS_PROBE_NOTHING;
|
||||
}
|
||||
@ -1751,20 +1769,14 @@ mbus_select_secondary_address(mbus_handle * handle, const char *mask)
|
||||
if (ret == -2)
|
||||
{
|
||||
/* check for more data (collision) */
|
||||
while (mbus_recv_frame(handle, &reply) != -1);
|
||||
|
||||
mbus_recv_frame_dummy(handle);
|
||||
return MBUS_PROBE_COLLISION;
|
||||
}
|
||||
|
||||
if (mbus_frame_type(&reply) == MBUS_FRAME_TYPE_ACK)
|
||||
{
|
||||
/* check for more data (collision) */
|
||||
while (mbus_recv_frame(handle, &reply) != -1)
|
||||
{
|
||||
ret = -2;
|
||||
}
|
||||
|
||||
if (ret == -2)
|
||||
if (mbus_recv_frame_dummy(handle))
|
||||
{
|
||||
return MBUS_PROBE_COLLISION;
|
||||
}
|
||||
@ -1809,7 +1821,7 @@ mbus_probe_secondary_address(mbus_handle * handle, const char *mask, char *match
|
||||
|
||||
ret = mbus_recv_frame(handle, &reply);
|
||||
|
||||
if (ret == -1)
|
||||
if (ret == -3)
|
||||
{
|
||||
return MBUS_PROBE_NOTHING;
|
||||
}
|
||||
@ -1905,7 +1917,7 @@ int mbus_read_slave(mbus_handle * handle, mbus_address *address, mbus_frame * re
|
||||
}
|
||||
}
|
||||
|
||||
if (mbus_recv_frame(handle, reply) == -1)
|
||||
if (mbus_recv_frame(handle, reply) != 0)
|
||||
{
|
||||
MBUS_ERROR("%s: Failed to receive M-Bus response frame.\n",
|
||||
__PRETTY_FUNCTION__);
|
||||
|
9
mbus/mbus-protocol-aux.h
Normal file → Executable file
9
mbus/mbus-protocol-aux.h
Normal file → Executable file
@ -179,6 +179,15 @@ int mbus_disconnect(mbus_handle * handle);
|
||||
int mbus_recv_frame(mbus_handle * handle, mbus_frame *frame);
|
||||
|
||||
/**
|
||||
* Used for handling collisions. Blocks as long as receiving frames or corrupted data.
|
||||
*
|
||||
* @param handle Initialized handle
|
||||
*
|
||||
* @return Zero when nothing received, one otherwise.
|
||||
*/
|
||||
int mbus_recv_frame_dummy(mbus_handle * handle);
|
||||
|
||||
/**
|
||||
* Sends frame using "unified" handle
|
||||
*
|
||||
* @param handle Initialized handle
|
||||
|
67
mbus/mbus-tcp.c
Normal file → Executable file
67
mbus/mbus-tcp.c
Normal file → Executable file
@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <mbus/mbus.h>
|
||||
#include <mbus/mbus-tcp.h>
|
||||
@ -161,69 +162,59 @@ mbus_tcp_send_frame(mbus_tcp_handle *handle, mbus_frame *frame)
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
int
|
||||
mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame)
|
||||
int mbus_tcp_recv_frame(mbus_tcp_handle *handle, mbus_frame *frame)
|
||||
{
|
||||
char buff[PACKET_BUFF_SIZE];
|
||||
int len, remaining, nread, timeouts;
|
||||
|
||||
if (handle == NULL || frame == NULL)
|
||||
{
|
||||
int len, remaining, nread;
|
||||
|
||||
if (handle == NULL || frame == NULL) {
|
||||
fprintf(stderr, "%s: Invalid parameter.\n", __PRETTY_FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset((void *)buff, 0, sizeof(buff));
|
||||
memset((void *) buff, 0, sizeof(buff));
|
||||
|
||||
//
|
||||
// read data until a packet is received
|
||||
//
|
||||
remaining = 1; // start by reading 1 byte
|
||||
len = 0;
|
||||
timeouts = 0;
|
||||
|
||||
do {
|
||||
|
||||
if ((nread = read(handle->sock, &buff[len], remaining)) == -1)
|
||||
{
|
||||
retry:
|
||||
nread = read(handle->sock, &buff[len], remaining);
|
||||
switch (nread) {
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
mbus_error_str_set("M-Bus tcp transport layer timeout has been reached.");
|
||||
return -3;
|
||||
}
|
||||
|
||||
mbus_error_str_set("M-Bus tcp transport layer failed to read data.");
|
||||
return -1;
|
||||
case 0:
|
||||
mbus_error_str_set("M-Bus tcp transport layer connection closed by remote host.");
|
||||
return -4;
|
||||
default:
|
||||
len += nread;
|
||||
}
|
||||
|
||||
if (nread == 0)
|
||||
{
|
||||
timeouts++;
|
||||
|
||||
if (timeouts >= 3)
|
||||
{
|
||||
// abort to avoid endless loop
|
||||
fprintf(stderr, "%s: Timeout\n", __PRETTY_FUNCTION__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len += nread;
|
||||
|
||||
} while ((remaining = mbus_parse(frame, buff, len)) > 0);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
// No data received
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// call the receive event function, if the callback function is registered
|
||||
//
|
||||
//
|
||||
if (_mbus_recv_event)
|
||||
_mbus_recv_event(MBUS_HANDLE_TYPE_TCP, buff, len);
|
||||
|
||||
if (remaining != 0)
|
||||
{
|
||||
|
||||
if (remaining < 0) {
|
||||
mbus_error_str_set("M-Bus layer failed to parse data.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user