Skip to content

Commit

Permalink
v0.7 64bit datatypes support added (#20)
Browse files Browse the repository at this point in the history
* Added 64 bit datatypes
SIGNED INT64 type - 'S'
FLOAT64 type - 'd'
UNSIGNED INT64 use capital 'I' and Numeric(Unsigned) in Zabbix
* updated readme, prepared 0.7 version
  • Loading branch information
v-zhuravlev authored Oct 5, 2017
1 parent ef86353 commit ccd9c08
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 14 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Resource locking (via IPC semaphores) is used when using RTU or Encapsulated Mod

## 1.B Install from tar.gz
Download from https://share.zabbix.com/dir-libraries/zabbix-loadable-modules/modbus-loadable-module
- `tar zxvpf libzbxmodbus-0.6.tar.gz`
- `cd libzbxmodbus-0.6`
- `tar zxvpf libzbxmodbus-0.7.tar.gz`
- `cd libzbxmodbus-0.7`
- `./configure --prefix=/etc/zabbix --enable-zabbix-[2|3|3.2]`
- `make`
- `make install`
Expand Down Expand Up @@ -86,17 +86,26 @@ and some optional params can be provided as well:

* **datatype(optional):**
provide datatype as single char:
b - for MODBUS_BIT
i - for MODBUS_INTEGER (unsigned)
s - for MODBUS_SIGNED_INT (NOTE: in Zabbix use 'Type of information' Numeric(float) )
l - for MODBUS_LONG
f - for MODBUS_FLOAT
`b` - for MODBUS_BIT
`i` - for MODBUS_INTEGER (unsigned)
`s` - for MODBUS_SIGNED_INT (NOTE: in Zabbix use 'Type of information' Numeric(float) )
`l` - for MODBUS_LONG, 32bit
`f` - for MODBUS_FLOAT, 32bit

There is also experimental support added for 64bit Modbus datatypes:
`S` - for MODBUS_SIGNED_INT64 (NOTE: in Zabbix use 'Type of information' Numeric(float) )
`I` - for MODBUS_INT64 (unsigned) (NOTE: in Zabbix use 'Type of information' Numeric(unsigned) )
`d` - for MODBUS_FLOAT64, 64 bit

otherwise, defaults will be used:
MODBUS_BIT if modbus function 1 or 2.
MODBUS_INTEGER if modbus_function 3 or 4.

Please also note Zabbix datatypes constraints when working with 64bit:
https://www.zabbix.com/documentation/3.4/manual/config/items

* **endianness(optional):**
Modbus endianness for long and float 32bit datatypes:
Modbus endianness(word swap) for long and float 32bit/64bit datatypes:
0 - for MODBUS_16BIT_LE (16 bit little endian)
1 - for MODBUS_16BIT_BE (16 bit big endian)
default is BE
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AC_INIT([libzbxmodbus], [0.6])
AC_INIT([libzbxmodbus], [0.7])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SUBDIRS([libmodbus])
Expand Down
75 changes: 70 additions & 5 deletions src/modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#define MODBUS_SIGNED_INT 's'
#define MODBUS_LONG 'l'
#define MODBUS_FLOAT 'f'
#define MODBUS_SIGNED_INT64 'S'
#define MODBUS_INT64 'I'
#define MODBUS_FLOAT64 'd'

#define MODBUS_16BIT_LE 0
#define MODBUS_16BIT_BE 1
Expand Down Expand Up @@ -141,6 +144,18 @@ unsigned long hash(unsigned char *str)
return hash;
}

/* Get a float from 8 bytes (Modbus) with swapped words (GH EF CD AB) */
double modbus_get_double(const uint16_t *src)
{
double d;
uint64_t i;

i = (((uint64_t)src[3]) << 48) + (((uint64_t)src[2]) << 32) + (((uint64_t)src[1]) << 16) + src[0];
memcpy(&d, &i, sizeof(double));

return d;
}

/******************************************************************************
* *
* Function: zbx_modbus_read_registers *
Expand Down Expand Up @@ -301,6 +316,7 @@ int zbx_modbus_read_registers(AGENT_REQUEST *request, AGENT_RESULT *result)
uint8_t tab_reg_bits[64];
int regs_to_read = 1;
if (datatype == MODBUS_FLOAT || datatype == MODBUS_LONG) { regs_to_read=2;}
else if (datatype == MODBUS_SIGNED_INT64 || datatype == MODBUS_INT64 || datatype == MODBUS_FLOAT64) { regs_to_read=4;}



Expand Down Expand Up @@ -347,7 +363,7 @@ int zbx_modbus_read_registers(AGENT_REQUEST *request, AGENT_RESULT *result)
}

//post-parsing
uint16_t temp_arr[2]; //output based on datatype
uint16_t temp_arr[4]; //output based on datatype
switch(datatype){

case MODBUS_BIT:
Expand All @@ -367,8 +383,7 @@ int zbx_modbus_read_registers(AGENT_REQUEST *request, AGENT_RESULT *result)
if (end == MODBUS_16BIT_LE) {
temp_arr[0] = tab_reg[0];
temp_arr[1] = tab_reg[1];
}
if (end == MODBUS_16BIT_BE) {
} else if (end == MODBUS_16BIT_BE) {
temp_arr[0] = tab_reg[1];
temp_arr[1] = tab_reg[0];
}
Expand All @@ -377,15 +392,65 @@ int zbx_modbus_read_registers(AGENT_REQUEST *request, AGENT_RESULT *result)

case MODBUS_LONG:
//MODBUS_GET_INT32_FROM_INT16 is doing BIG_ENDIAN for register pair, so inverse registers (sort of hack)
if (end == MODBUS_16BIT_LE) {
if (end == MODBUS_16BIT_LE) {//word swap
temp_arr[0] = tab_reg[1];
temp_arr[1] = tab_reg[0];
} else if (end == MODBUS_16BIT_BE) {
temp_arr[0] = tab_reg[0];
temp_arr[1] = tab_reg[1];
}
SET_UI64_RESULT(result, MODBUS_GET_INT32_FROM_INT16(temp_arr, 0));
break;

case MODBUS_SIGNED_INT64:
if (end == MODBUS_16BIT_LE) {
temp_arr[0] = tab_reg[3];
temp_arr[1] = tab_reg[2];
temp_arr[2] = tab_reg[1];
temp_arr[3] = tab_reg[0];
}
if (end == MODBUS_16BIT_BE) {
temp_arr[0] = tab_reg[0];
temp_arr[1] = tab_reg[1];
temp_arr[2] = tab_reg[2];
temp_arr[3] = tab_reg[3];
}
SET_UI64_RESULT(result, MODBUS_GET_INT32_FROM_INT16(temp_arr, 0));
SET_DBL_RESULT(result, ((int64_t)MODBUS_GET_INT64_FROM_INT16(temp_arr,0)));
break;

case MODBUS_INT64:
//INT64
if (end == MODBUS_16BIT_LE) {
temp_arr[0] = tab_reg[3];
temp_arr[1] = tab_reg[2];
temp_arr[2] = tab_reg[1];
temp_arr[3] = tab_reg[0];
}
if (end == MODBUS_16BIT_BE) {
temp_arr[0] = tab_reg[0];
temp_arr[1] = tab_reg[1];
temp_arr[2] = tab_reg[2];
temp_arr[3] = tab_reg[3];
}

SET_UI64_RESULT(result, ((uint64_t)MODBUS_GET_INT64_FROM_INT16(temp_arr,0)));
break;

case MODBUS_FLOAT64:

if (end == MODBUS_16BIT_LE) {
temp_arr[0] = tab_reg[3];
temp_arr[1] = tab_reg[2];
temp_arr[2] = tab_reg[1];
temp_arr[3] = tab_reg[0];
}
if (end == MODBUS_16BIT_BE) {
temp_arr[0] = tab_reg[0];
temp_arr[1] = tab_reg[1];
temp_arr[2] = tab_reg[2];
temp_arr[3] = tab_reg[3];
}
SET_DBL_RESULT(result, modbus_get_double(temp_arr));
break;

default :
Expand Down

0 comments on commit ccd9c08

Please sign in to comment.