3 Commits

Author SHA1 Message Date
2dc3daaf70 Prepare new release 0.9.0 2019-02-22 19:08:04 +01:00
36a85d3737 Add product string of Hydrometer Sharky 775 2019-02-20 22:01:47 +01:00
2f9fa5ccc8 Implement negative BCD number (Type A)
According to W4B21021.pdf Appendix A a hex code Fh in the MSD
position signals a negative BCD number.
2019-02-20 22:01:47 +01:00
8 changed files with 107 additions and 76 deletions

View File

@ -11,7 +11,6 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <mbus/mbus.h>
static int debug = 0;
@ -55,43 +54,60 @@ main(int argc, char **argv)
{
mbus_handle *handle;
char *device;
int address, retries = 0, timeout = 0;
int address, retries = 0;
long baudrate = 9600;
int opt, ret;
int ret;
while ((opt = getopt(argc, argv, "db:r:t:")) != -1)
if (argc == 2)
{
switch (opt)
{
case 'd':
debug = 1;
break;
case 'b':
baudrate = atol(optarg);
break;
case 'r':
retries = atoi(optarg);
break;
case 't':
timeout = atoi(optarg);
break;
default:
fprintf(stderr,"usage: %s [-d] [-b BAUDRATE] [-r RETRIES] [-t TIMEOUT] device\n",
argv[0]);
return 0;
}
device = argv[1];
}
if (optind >= argc) {
fprintf(stderr,"usage: %s [-d] [-b BAUDRATE] [-r RETRIES] [-t TIMEOUT] device\n",
argv[0]);
else if (argc == 3 && strcmp(argv[1], "-d") == 0)
{
debug = 1;
device = argv[2];
}
else if (argc == 4 && strcmp(argv[1], "-b") == 0)
{
baudrate = atol(argv[2]);
device = argv[3];
}
else if (argc == 4 && strcmp(argv[1], "-r") == 0)
{
retries = atoi(argv[2]);
device = argv[3];
}
else if (argc == 5 && strcmp(argv[1], "-d") == 0 && strcmp(argv[2], "-b") == 0)
{
debug = 1;
baudrate = atol(argv[3]);
device = argv[4];
}
else if (argc == 5 && strcmp(argv[1], "-d") == 0 && strcmp(argv[2], "-r") == 0)
{
debug = 1;
retries = atoi(argv[3]);
device = argv[4];
}
else if (argc == 6 && strcmp(argv[1], "-b") == 0 && strcmp(argv[3], "-r") == 0)
{
baudrate = atol(argv[2]);
retries = atoi(argv[4]);
device = argv[5];
}
else if (argc == 7 && strcmp(argv[1], "-d") == 0 && strcmp(argv[2], "-b") == 0 && strcmp(argv[4], "-r") == 0)
{
debug = 1;
baudrate = atol(argv[3]);
retries = atoi(argv[5]);
device = argv[6];
}
else
{
fprintf(stderr,"usage: %s [-d] [-b BAUDRATE] [-r RETRIES] device\n", argv[0]);
return 0;
}
device = argv[optind];
if ((handle = mbus_context_serial(device)) == NULL)
{
fprintf(stderr,"Scan failed: Could not initialize M-Bus context: %s\n", mbus_error_str());
@ -116,12 +132,6 @@ main(int argc, char **argv)
return 1;
}
if (mbus_context_set_option(handle, MBUS_OPTION_TIMEOUT_OFFSET, timeout) == -1)
{
fprintf(stderr,"Failed to set timeout offset\n");
return 1;
}
if (mbus_serial_set_baudrate(handle, baudrate) == -1)
{
fprintf(stderr,"Failed to set baud rate.\n");

View File

@ -10,7 +10,7 @@ dnl ----------------------------------------------------------------------------
LT_CONFIG_LTDL_DIR([libltdl])
AC_INIT([libmbus], [0.8.0], [info@rscada.se], [libmbus], [http://www.rscada.se/libmbus/])
AC_INIT([libmbus], [0.9.0], [info@rscada.se], [libmbus], [http://www.rscada.se/libmbus/])
AC_CONFIG_AUX_DIR([libltdl/config])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
@ -18,7 +18,7 @@ AM_PROG_LIBTOOL
# fix for automake 1.11 & 1.12
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
LDFLAGS="$LDFLAGS -version-info 0:8:0"
LDFLAGS="$LDFLAGS -version-info 0:9:0"
dnl ----------------------
dnl

View File

@ -11,10 +11,10 @@
Summary: Open source M-bus (Meter-Bus) library
Name: libmbus
Version: 0.8.0
Version: 0.9.0
Release: 1
Source: http://www.rscada.se/public-dist/%{name}-%{version}.tar.gz
URL: http://www.rscada.se/libmbus/
Source: https://github.com/rscada/%{name}/archive/%{version}.tar.gz
URL: https://github.com/rscada/libmbus/
License: BSD
Vendor: Raditex Control AB
Packager: Stefan Wahren <info@lategoodbye.de>
@ -68,9 +68,8 @@ rm -rf "%buildroot"
%{_bindir}/mbus-serial-*
%{_bindir}/mbus-tcp-*
%{_libdir}/libmbus.so*
# man pages doesn't exist in this version
# %{_mandir}/man1/libmbus.1
# %{_mandir}/man1/mbus-*
%{_mandir}/man1/libmbus.1
%{_mandir}/man1/mbus-*
%files devel
%defattr (-,root,root)
@ -80,5 +79,9 @@ rm -rf "%buildroot"
%{_libdir}/pkgconfig/libmbus.pc
%changelog
* Fri Feb 22 2019 Stefan Wahren <info@lategoodbye.de> - 0.9.0-1
- switch to github repo
- enable man pages
* Fri Mar 29 2013 Stefan Wahren <info@lategoodbye.de> - 0.8.0-1
- Initial package based on the last official release
- Initial package based on the last official release

View File

@ -1519,7 +1519,6 @@ mbus_context_serial(const char *device)
handle->max_data_retry = 3;
handle->max_search_retry = 1;
handle->timeout_offset = 0;
handle->is_serial = 1;
handle->purge_first_frame = MBUS_FRAME_PURGE_M2S;
handle->auxdata = serial_data;
@ -1568,7 +1567,6 @@ mbus_context_tcp(const char *host, uint16_t port)
handle->max_data_retry = 3;
handle->max_search_retry = 1;
handle->timeout_offset = 0;
handle->is_serial = 0;
handle->purge_first_frame = MBUS_FRAME_PURGE_M2S;
handle->auxdata = tcp_data;
@ -1654,13 +1652,6 @@ mbus_context_set_option(mbus_handle * handle, mbus_context_option option, long v
return 0;
}
break;
case MBUS_OPTION_TIMEOUT_OFFSET:
if ((value >= 0) && (value <= 100))
{
handle->timeout_offset = value;
return 0;
}
break;
case MBUS_OPTION_PURGE_FIRST_FRAME:
if ((value == MBUS_FRAME_PURGE_NONE) ||
(value == MBUS_FRAME_PURGE_M2S) ||

View File

@ -87,7 +87,6 @@ typedef struct _mbus_handle {
int fd;
int max_data_retry;
int max_search_retry;
unsigned int timeout_offset;
char purge_first_frame;
char is_serial; /**< _handle type (non zero for serial) */
int (*open) (struct _mbus_handle *handle);
@ -155,8 +154,7 @@ typedef struct _mbus_record {
typedef enum _mbus_context_option {
MBUS_OPTION_MAX_DATA_RETRY, /**< option defines the maximum attempts of data request retransmission */
MBUS_OPTION_MAX_SEARCH_RETRY, /**< option defines the maximum attempts of search request retransmission */
MBUS_OPTION_PURGE_FIRST_FRAME, /**< option controls the echo cancelation for mbus_recv_frame */
MBUS_OPTION_TIMEOUT_OFFSET, /**< option defines the additional timeout offset */
MBUS_OPTION_PURGE_FIRST_FRAME /**< option controls the echo cancelation for mbus_recv_frame */
} mbus_context_option;
/**

View File

@ -461,9 +461,9 @@ mbus_data_bcd_encode(unsigned char *bcd_data, size_t bcd_data_size, int value)
int v0, v1, v2, x1, x2;
size_t i;
if (bcd_data && bcd_data_size && (value >= 0))
if (bcd_data && bcd_data_size)
{
v2 = value;
v2 = abs(value);
for (i = 0; i < bcd_data_size; i++)
{
@ -477,6 +477,11 @@ mbus_data_bcd_encode(unsigned char *bcd_data, size_t bcd_data_size, int value)
bcd_data[bcd_data_size-1-i] = (x2 << 4) | x1;
}
if (value < 0)
{
bcd_data[bcd_data_size-1] |= 0xF0;
}
return 0;
}
@ -498,8 +503,20 @@ mbus_data_bcd_decode(unsigned char *bcd_data, size_t bcd_data_size)
{
for (i = bcd_data_size; i > 0; i--)
{
val = (val * 10) + ((bcd_data[i-1]>>4) & 0xF);
val = (val * 10) + ( bcd_data[i-1] & 0xF);
val = (val * 10);
if (bcd_data[i-1]>>4 < 0xA)
{
val += ((bcd_data[i-1]>>4) & 0xF);
}
val = (val * 10) + ( bcd_data[i-1] & 0xF);
}
// hex code Fh in the MSD position signals a negative BCD number
if (bcd_data[bcd_data_size-1]>>4 == 0xF)
{
val *= -1;
}
return val;
@ -1088,6 +1105,9 @@ mbus_data_product_name(mbus_data_variable_header *header)
case 0x28:
strcpy(buff,"ABB F95 Typ US770");
break;
case 0x2F:
strcpy(buff,"Hydrometer Sharky 775");
break;
}
}
else if (manufacturer == mbus_manufacturer_id("JAN"))

View File

@ -72,10 +72,13 @@ mbus_serial_connect(mbus_handle *handle)
// between the end of a master send telegram and the beginning of the response telegram of the slave shall be
// between 11 bit times and (330 bit times + 50ms).
//
// For 2400Bd this means (330 + 11) / 2400 + 0.05 = 188.75 ms (added 11 bit periods to receive first byte).
// I.e. timeout of 0.2s seems appropriate for 2400Bd.
// Nowadays the usage of USB to serial adapter is very common, which could
// result in additional delay of 100 ms in worst case.
//
// For 2400Bd this means (330 + 11) / 2400 + 0.15 = 292 ms (added 11 bit periods to receive first byte).
// I.e. timeout of 0.3s seems appropriate for 2400Bd.
term->c_cc[VTIME] = (cc_t) 2 + handle->timeout_offset; // Timeout in 1/10 sec
term->c_cc[VTIME] = (cc_t) 3; // Timeout in 1/10 sec
cfsetispeed(term, B2400);
cfsetospeed(term, B2400);
@ -113,51 +116,48 @@ mbus_serial_set_baudrate(mbus_handle *handle, long baudrate)
{
case 300:
speed = B300;
serial_data->t.c_cc[VTIME] = (cc_t) 12; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 13; // Timeout in 1/10 sec
break;
case 600:
speed = B600;
serial_data->t.c_cc[VTIME] = (cc_t) 6; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 8; // Timeout in 1/10 sec
break;
case 1200:
speed = B1200;
serial_data->t.c_cc[VTIME] = (cc_t) 4; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 5; // Timeout in 1/10 sec
break;
case 2400:
speed = B2400;
serial_data->t.c_cc[VTIME] = (cc_t) 2; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 3; // Timeout in 1/10 sec
break;
case 4800:
speed = B4800;
serial_data->t.c_cc[VTIME] = (cc_t) 2; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 3; // Timeout in 1/10 sec
break;
case 9600:
speed = B9600;
serial_data->t.c_cc[VTIME] = (cc_t) 1; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 2; // Timeout in 1/10 sec
break;
case 19200:
speed = B19200;
serial_data->t.c_cc[VTIME] = (cc_t) 1; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 2; // Timeout in 1/10 sec
break;
case 38400:
speed = B38400;
serial_data->t.c_cc[VTIME] = (cc_t) 1; // Timeout in 1/10 sec
serial_data->t.c_cc[VTIME] = (cc_t) 2; // Timeout in 1/10 sec
break;
default:
return -1; // unsupported baudrate
}
// Add timeout offset for additional delay
serial_data->t.c_cc[VTIME] += handle->timeout_offset;
// Set input baud rate
if (cfsetispeed(&(serial_data->t), speed) != 0)
{

View File

@ -1,5 +1,14 @@
Release notes for libmbus
Version 0.9.0 (2019-02-22):
Added support for negative BCD numbers (type A) and date time CP48 (type I),
new program (set primary address), extended XML output (storage number,
tariff, device), echo cancelation and better retry handling. Also this version
has countless bug fixes.
Many thanks to all contributers
Version 0.8.0 (2012-06-18):
--------------------------