28 #define MBUS_DATA_LENGTH 0xF6 250 strcpy(buffer, prefix);
252 va_start(valist, format);
253 vsprintf(&buffer[strlen(buffer)], format, valist);
271 if (vplSetIOSignal(RF_OFF, !power) != 0)
273 mbusDebug(__func__,
"ERR (%d): Faield to set signal", __LINE__);
279 vplSetIOSignal(RF_CFG, 0);
282 vplSetIOSignal(RF_CFG, 1);
312 mbusDebug(__func__,
"ERR (%d): Already in config mode", __LINE__);
317 if (vplSetIOSignal(RF_CFG, 0) != 0)
319 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
323 for (
int try = 0;
try < 3; ++
try)
326 if (tcflush(
fd, TCIOFLUSH))
328 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
335 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
339 if (vplSetIOSignal(RF_CFG, 1) != 0)
341 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
347 rc = write(
fd, &cmd, 1);
350 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
355 mbusDebug(__func__,
"ERR (%d): failed to send exit command",
367 while (rc == 0 && tries < 3)
369 rc = read(
fd, &reply, 1);
372 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
380 if (vplSetIOSignal(RF_CFG, 0) != 0)
382 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
385 if ((rc == 1) && reply ==
'>')
393 return (reply ==
'>') ? 0 : 1;
413 mbusDebug(__func__,
"ERR (%d): config not active", __LINE__);
418 int rc = write(
fd, &cmd, 1);
421 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
426 mbusDebug(__func__,
"ERR (%d): failed to send exit command", __LINE__);
434 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
438 if (tcflush(
fd, TCIOFLUSH))
440 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
471 rc = write(
fd, &cmd, 1);
474 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
479 mbusDebug(__func__,
"ERR (%d): failed to send 0x%02X", __LINE__, cmd);
483 if (data && d_size > 0)
485 rc = write(
fd, data, d_size);
488 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
493 mbusDebug(__func__,
"ERR (%d): failed to send 0x%02X", __LINE__, cmd);
501 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
508 int remaining = r_size;
509 for (
int try = 0;
try < 5;
try++)
511 int rc = read(
fd, &reply[r_size - remaining], remaining);
514 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
524 "ERR (%d): unexpected reply to 0x%02X (missing %d of %d)",
525 __LINE__, (cmd & 0xFF), remaining, r_size);
532 for (
int try = 0;
try < 5;
try++)
534 rc = read(
fd, &cfm, 1);
537 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
540 if ((rc == 1) && cfm ==
'>')
546 mbusDebug(__func__,
"ERR (%d): no reply to 0x%02X, 0x%x(%c)", __LINE__,
592 int rc = write(
fd, &cmd, 1);
595 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
600 mbusDebug(__func__,
"ERR (%d): failed to send 0x%02X", __LINE__, cmd);
607 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
630 memset(reply, 0x00, size);
631 for (
int i = 0; i < size; ++i)
637 sprintf(&buf[i * 3],
"%02X ", reply[i]);
640 mbusDebug(__func__,
"%s = '%s'", name, buf);
657 memset(buffer, 0x00, size);
658 for (
int i = 0; i < size; ++i)
737 if (only_installed >= 0)
763 static int __attribute__( (unused))
772 mbusDebug(__func__,
"ERR (%d): Already in config mode", __LINE__);
776 if (vplSetIOSignal(RF_CFG, 0) != 0)
778 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
781 for (
int try = 0;
try < 3; ++
try)
784 if (tcflush(
fd, TCIOFLUSH))
786 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
793 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
797 if (vplSetIOSignal(RF_CFG, 1) != 0)
799 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
805 rc = write(
fd, &cmd, 1);
808 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
813 mbusDebug(__func__,
"ERR (%d): failed to send exit command",
825 while (rc == 0 && tries < 3)
827 rc = read(
fd, &reply, 1);
830 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
837 if ((rc == 1) && reply ==
'>')
844 if (vplSetIOSignal(RF_CFG, 0) != 0)
846 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
856 if (vplSetIOSignal(RF_CFG, 0) != 0)
858 mbusDebug(__func__,
"ERR (%d): Failed to set signal", __LINE__);
889 tcflush(
fd, TCIOFLUSH);
892 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
926 mbusDebug(__func__,
"ERR: Communication interface already opened:");
930 if (vplFsMapFile(port_path, 200,
"dev:ser3"))
932 mbusDebug(__func__,
"ERR: Failed to open port:");
936 fd = open(port_path, O_RDWR | O_NOCTTY | O_SYNC);
939 mbusDebug(__func__,
"ERR: Failed to open '%s': %s", port_path,
944 memset(&tty, 0,
sizeof tty);
945 if (tcgetattr(
fd, &tty) != 0)
947 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
952 cfsetospeed(&tty, B19200);
953 cfsetispeed(&tty, B19200);
955 tty.c_cflag |= (CLOCAL | CREAD);
956 tty.c_cflag &= ~CSIZE;
958 tty.c_cflag &= ~PARENB;
959 tty.c_cflag &= ~CSTOPB;
960 tty.c_cflag &= ~CRTSCTS;
963 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL
965 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
966 tty.c_oflag &= ~OPOST;
969 tty.c_cc[VMIN] = (cc_t) 0;
970 tty.c_cc[VTIME] = (cc_t) 10;
972 if (tcsetattr(
fd, TCSANOW, &tty) != 0)
974 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
982 for (i = 0; i < 5; ++i)
994 mbusDebug(__func__,
"ERR (%d): failed to reset module", __LINE__);
1050 send = write(
fd, &cmd, 1);
1053 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1058 mbusDebug(__func__,
"(%d): Failed to write send request", __LINE__);
1065 send = write(
fd, &size, 1);
1068 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1073 mbusDebug(__func__,
"(%d): Failed to write data length", __LINE__);
1076 send = write(
fd, data, size);
1079 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1084 mbusDebug(__func__,
"(%d): Failed to write data (%d of %d)", __LINE__,
1107 int rlen, data_size;
1108 int remaining =
sizeof(*start);
1111 rlen = read(
fd, &start->
length, 1);
1114 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1124 mbusDebug(__func__,
"(%d): zero length frame received", __LINE__);
1131 rlen = read(
fd, (&start->
length) + 1, remaining);
1134 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1137 if (rlen != remaining)
1139 mbusDebug(__func__,
"(%d): failed to receive start frame (%d of %d)",
1140 __LINE__, rlen, remaining);
1141 tcflush(
fd, TCIFLUSH);
1145 data_size = start->
length -
sizeof(*start) + 1;
1149 mbusDebug(__func__,
"(%d): invalid frame length (%d < %d)", __LINE__,
1150 start->
length,
sizeof(*start) + 1);
1151 tcflush(
fd, TCIFLUSH);
1163 while (pos < data_size && tries < 3)
1165 rlen = read(
fd, &data[pos], data_size - pos);
1168 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1175 if (pos != data_size)
1177 mbusDebug(__func__,
"(%d): failed to receive data frame (%d of %d)",
1178 __LINE__, pos, data_size);
1179 tcflush(
fd, TCIFLUSH);
1187 rlen = read(
fd, &buf, 1);
1190 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1202 start->
length = (uint8) data_size;
1229 if (idx > 64 || idx <= 0)
1234 memcpy(&addr[0], &
id, 4);
1235 memcpy(&addr[4], &manufacturer, 2);
1236 memcpy(&addr[6], &version, 1);
1237 memcpy(&addr[7], &type, 1);
1285 mbusDebug(__func__,
"Signal quality = %d", reply[0]);
1290 mbusDebug(__func__,
"RSSI = %d (%d dBm)", reply[0],
1296 mbusDebug(__func__,
"Temperature = %d C", (reply[0] - 128));
1301 mbusDebug(__func__,
"VCC = %dmV", (reply[0] * 30));
1308 mbusDebug(__func__,
"MBUS_MODE = 0x%02X", reply[0]);
1313 mbusDebug(__func__,
"DATA_INTERFACE = 0x%02X", reply[0]);
1319 mbusDebug(__func__,
"PART_NUMBER = '%s'", reply);
1325 mbusDebug(__func__,
"HW_REV_NO = '%s'", reply);
1331 mbusDebug(__func__,
"FW_REV_NO = '%s'", reply);
1336 for (i = 0; i < 8; i++)
1338 sprintf(&serial[i * 3],
"%02X ", reply[i]);
1340 serial[8 * 3 - 1] = 0;
1341 mbusDebug(__func__,
"SERIAL_NUMBER = %s", serial);
1345 mbusDebug(__func__,
"INSTALL_MODE = 0x%02X", reply[0]);
1349 mbusDebug(__func__,
"RSSI_MODE = 0x%02X", reply[0]);
1373 static int32 MODDECL
1378 if (pthread_mutex_lock(&
lock))
1380 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1385 pthread_mutex_unlock(&
lock);
1395 static int32 MODDECL
1397 void* pBase __attribute__((unused)))
1399 if (pthread_mutex_lock(&
lock))
1401 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1406 pthread_mutex_unlock(&
lock);
1416 static int32 MODDECL
1423 if (pthread_mutex_lock(&
lock))
1425 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1443 pthread_mutex_unlock(&
lock);
1456 static int32 MODDECL
1463 mbusDebug(__func__,
"ERR (%d): missing data", __LINE__);
1469 mbusDebug(__func__,
"ERR (%d): illegal data length %d", __LINE__,
1476 mbusDebug(__func__,
"ERR (%d): illegal control value %d", __LINE__,
1481 if (pthread_mutex_lock(&
lock))
1483 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1489 pthread_mutex_unlock(&
lock);
1534 static int32 MODDECL
1536 void* pBase __attribute__((unused)))
1538 if (pthread_mutex_lock(&
lock))
1540 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1547 mbusDebug(__func__,
"error resetting interface (%d)", rc);
1552 pthread_mutex_unlock(&
lock);
1561 static int32 MODDECL
1566 if (pthread_mutex_lock(&
lock))
1568 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1573 pthread_mutex_unlock(&
lock);
1583 static int32 MODDECL
1588 if (pthread_mutex_lock(&
lock))
1590 mbusDebug(__func__,
"ERR (%d): failed to get lock", __LINE__);
1596 pthread_mutex_unlock(&
lock);
1622 pthread_mutexattr_t lock_attr;
1623 vplFunctionEntry ftable[] =
1638 rc = pthread_mutexattr_init(&lock_attr);
1641 mbusDebug(__func__,
"ERR (%d): %d", __LINE__, rc);
1644 rc = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
1647 mbusDebug(__func__,
"ERR (%d): %d", __LINE__, rc);
1650 rc = pthread_mutex_init(&
lock, &lock_attr);
1653 mbusDebug(__func__,
"ERR (%d): %d", __LINE__, rc);
1658 rc = vplInstallFunctions(
"mod_mbus", ftable);
1662 mbusDebug(__func__,
"failed to install 'mod_mbus' functions err %d", rc);
1666 if (vplSetIOSignal(RF_CFG, 0) != 0)
1668 mbusDebug(__func__,
"ERR (%d): %s", __LINE__, strerror(errno));
1698 case EVENT_SHUTDOWN:
1702 case EVENT_POWERFAIL:
1713 case EVENT_POWERSAVE:
1725 mbusDebug(__func__,
"Unknown event %d", event);
static pthread_mutex_t lock
thread synchronization lock
static int mbusOpen(int8 mode, int8 rssi)
Opens the connection to the M-Bus module.
int8 rssi
Set to true to include the signal strength (RSSI) for each valid packet.
int16 length
The length of the additional data in the frame.
static int mbusSend(int16 c, int8 *data, int8 size)
Send an M-BUS packet.
int8 data[MBUS_DATA_LENGTH]
The additional data received from the M-Bus module. Only the first [length] bytes are valid...
static int mbus_config(int8 mode, int8 rssi, int8 only_installed)
Configure a number of common settings.
FUNCTION mbusSend Defines the data structure of the VPL function mbusSend.
static int32 MODDECL mbusCallInfo(HANDLE *pCPU, void *pBase)
Perform a series of tests to validate communication.
uint8 length
L-field : Length of full frame not including length or any start/stop bytes.
int8 type
Device Type. Part of the address of the slave.
int16 error
error value from call, set by VPL
int16 manufacturer
Manufacturer ID. Part of the address of the slave.
int32 id
Identification number/serial number. Part of the address of the slave.
int16 retval
return value from call, set by VPL
static int cfg_active
Flag to monitor if we are in config mode.
int8 version
Version number. Part of the device address.
FUNCTION mbusReceive Defines the data structure of the VPL function mbusReceive.
int8 only_installed
Set to true to only show packets from installed slaves.
int16 rssi
The signal strength (RSSI), if enabled in mbusOpen().
uint8 type
A-Field[6]:Device type part of address field.
static int32 MODDECL mbusCallSetFilter(HANDLE *pCPU, void *pBase)
Set mode.
static int fd
serial port handle
static int32 MODDECL mbusCallOpen(HANDLE *pCPU, void *pBase)
Open communication interface to the module.
static int mbus_read_reg(int8 reg, int size, const char *name)
Reads the value of one or more registers in the M-Bus module and prints the value to the device outpu...
int8 type
Device Type. Part of the device address.
FUNCTION mbusOpen Defines the data structure of the VPL function mbusOpen.
uint32 id
A-Field[4]:ID/Serial number part of address field.
static int mbusConfigCmd(uint8 cmd, uint8 *reply, int size)
Send a single command/argument.
static void mbusDebug(const char *prefix, const char *format,...)
Send a debug message to the device output in the format "<prefix>:<formated string>".
static int mbusConfigExit(void)
Exit configuration mode.
int16 retval
return value from call, set by VPL
FUNCTION mbusSetFilter Defines the data structure of the VPL function mbusSetFilter.
static int mbus_config_mem_reg(uint8 reg, uint8 val)
Change the value of a register in the M-Bus module.
int16 error
error value from call, set by VPL
static int cfg_activated
Flag to monitor if we have received the reply showing the we are in config mode.
static int mbusPower(uint8 power)
Control power to module.
void moduleNotify(int event, int parm)
This function is called by the firmware to notify the module about an event.
static int32 MODDECL mbusCallClose(HANDLE *pCPU, void *pBase)
Close communication interface to the module.
int8 version
Version number. Part of the address of the slave.
static int mbus_read_regs(int8 reg, uint8 *buffer, int size)
Reads the value of one or more registers in the M-Bus module and stores the value in the provided buf...
int16 retval
return value from call, set by VPL
static int mbusReceive(tdef_mbus_start_frame *start, int8 *data, int16 *rssi)
Receive a new frame from the M-Bus module.
static int mbus_info(void)
Print some information about the RF module to the device output.
static int mbusConfigTransact(uint8 cmd, uint8 *data, int d_size, uint8 *reply, int r_size)
Send a single configuration command with additional data and receive the reply.
int32 id
Identification number/serial number. Part of the device address.
int16 error
error value from call, set by VPL
int16 retval
return value from call, set by VPL
The first block of data when a new MBUS message is received.
int8 control
Control field.
static int mbusConfigFactoryReset(void)
This function performs a factory reset of the RF module.
static int32 MODDECL mbusCallRegisterSlave(HANDLE *pCPU, void *pBase)
Register a slave device.
static int rssi_included
Flag to keep track of whether the RSSI is included in each packet.
uint16 manufacturer
M-Field : Manufacture ID, e.g. 0x0646 (ARF)
int16 control
Value of the control field to use when sending.
int16 idx
The index of the slave to register. 1-64.
static int32 MODDECL mbusCallSend(HANDLE *pCPU, void *pBase)
Send a MBUS message.
int16 error
error value from call, set by VPL
STRUCT_BLOCK mbusFrame Defines the data structure of the VPL STRUCT_BLOCK mbusFrame.
static int mbus_register_slave(int idx, int16 manufacturer, int32 id, int8 version, int8 type, uint8 *key)
Registers/installs a slave device on the M-Bus module.
int16 length
Length of the data to send.
static int mbusClose(void)
Closes the communication interface.
int16 error
error value from call, set by VPL
uint8 * key
Encryption key, 16 bytes. Can be set to NULL when encryption is not used.
uint8 control
C-field : Control byte used to identify packet type.
#define MBUS_DATA_LENGTH
Maximum size of a MBUS message not including header information.
int16 retval
return value from call, set by VPL
int16 manufacture
Manufacture ID. Part of the device address.
FUNCTION mbusRegisterSlave Defines the data structure of the VPL function mbusRegisterSlave.
tdef_mbus_frame * frame
The provided struct is filled with the values of a received M-Bus frame.
int moduleInit(void)
This function is called by the firmware when 'extModuleLoad' is called.
static int32 MODDECL mbusCallReceive(HANDLE *pCPU, void *pBase)
Check if any MBUS packets has been received.
uint8 version
A-Field[5]:Device version part of address field.
int8 mode
The M-Bus mode to use.
static int mbusConfigEnter(void)
Entering configuration mode.
static int mbusConfigData(uint8 cmd)
Send configuration data.