From 96fb4a9335b862f15a1c6c4e99e501c241ae06ef Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 8 Apr 2012 18:43:13 +0200 Subject: [PATCH] Added program to switch baudrate of M-Bus slave (untested) --- bin/Makefile.am | 7 ++- bin/mbus-serial-switch-baudrate.c | 90 +++++++++++++++++++++++++++++++ mbus/mbus-protocol-aux.c | 64 ++++++++++++++++++++++ mbus/mbus-protocol-aux.h | 11 ++++ 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 bin/mbus-serial-switch-baudrate.c diff --git a/bin/Makefile.am b/bin/Makefile.am index 08fd712..ca63f80 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -16,7 +16,8 @@ noinst_HEADERS = bin_PROGRAMS = mbus-tcp-scan mbus-tcp-request-data \ mbus-tcp-select-secondary mbus-tcp-scan-secondary \ mbus-serial-scan mbus-serial-request-data \ - mbus-serial-select-secondary mbus-serial-scan-secondary + mbus-serial-select-secondary mbus-serial-scan-secondary \ + mbus-serial-switch-baudrate # tcp mbus_tcp_scan_LDFLAGS = -L$(top_builddir)/mbus @@ -52,3 +53,7 @@ mbus_serial_scan_secondary_LDFLAGS = -L$(top_builddir)/mbus mbus_serial_scan_secondary_LDADD = -lmbus mbus_serial_scan_secondary_SOURCES = mbus-serial-scan-secondary.c +mbus_serial_switch_baudrate_LDFLAGS = -L$(top_builddir)/mbus +mbus_serial_switch_baudrate_LDADD = -lmbus +mbus_serial_switch_baudrate_SOURCES = mbus-serial-switch-baudrate.c + diff --git a/bin/mbus-serial-switch-baudrate.c b/bin/mbus-serial-switch-baudrate.c new file mode 100644 index 0000000..ba7c1ee --- /dev/null +++ b/bin/mbus-serial-switch-baudrate.c @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// Copyright (C) 2010-2012, Robert Johansson and contributors, Raditex AB +// All rights reserved. +// +// FreeSCADA +// http://www.FreeSCADA.com +// freescada@freescada.com +// +// Contributors: +// Large parts of this file was contributed by Stefan Wahren. +// +//------------------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include +#include + + +//------------------------------------------------------------------------------ +// Execution starts here: +//------------------------------------------------------------------------------ +int +main(int argc, char **argv) +{ + mbus_handle *handle; + mbus_frame reply; + char *device; + int address, ret; + int source_baudrate = 9600, target_baudrate; + + if (argc == 4) + { + device = argv[1]; + address = atoi(argv[2]); + target_baudrate = atoi(argv[3]); + } + else if (argc == 6 && strcmp(argv[1], "-b") == 0) + { + source_baudrate = atoi(argv[2]); + device = argv[3]; + address = atoi(argv[4]); + target_baudrate = atoi(argv[5]); + } + else + { + fprintf(stderr, "usage: %s device address target-baudrate\n", argv[0]); + return 0; + } + + if ((handle = mbus_connect_serial(device)) == NULL) + { + printf("Failed to setup connection to M-bus device: %s\n", mbus_error_str()); + return -1; + } + + if (mbus_serial_set_baudrate(handle->m_serial_handle, source_baudrate) == -1) + { + printf("Failed to set baud rate.\n"); + return -1; + } + + if (mbus_send_switch_baudrate_frame(handle, address, target_baudrate) == -1) + { + printf("Failed to send switch baudrate frame: %s\n", mbus_error_str()); + return -1; + } + + ret = mbus_recv_frame(handle, &reply); + + if (ret == -1) + { + printf("No reply from device\n"); + return -1; + } + + if (mbus_frame_type(&reply) != MBUS_FRAME_TYPE_ACK) + { + printf("Unknown reply:\n"); + mbus_frame_print(&reply); + } + + mbus_disconnect(handle); + return 0; +} + diff --git a/mbus/mbus-protocol-aux.c b/mbus/mbus-protocol-aux.c index 9b72139..828effc 100644 --- a/mbus/mbus-protocol-aux.c +++ b/mbus/mbus-protocol-aux.c @@ -1253,6 +1253,70 @@ mbus_send_select_frame(mbus_handle * handle, const char *secondary_addr_str) return 0; } +//------------------------------------------------------------------------------ +// send a user data packet from master to slave: the packet let the +// adressed slave(s) switch to the given baudrate +//------------------------------------------------------------------------------ +int +mbus_send_switch_baudrate_frame(mbus_handle * handle, int address, int baudrate) +{ + int retval = 0; + int control_information = 0; + mbus_frame *frame; + + switch (baudrate) + { + case 300: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_300; + break; + case 600: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_600; + break; + case 1200: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_1200; + break; + case 2400: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_2400; + break; + case 4800: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_4800; + break; + case 9600: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_9600; + break; + case 19200: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_19200; + break; + case 38400: + control_information = MBUS_CONTROL_INFO_SET_BAUDRATE_38400; + break; + default: + MBUS_ERROR("%s: invalid baudrate %d\n", __PRETTY_FUNCTION__, baudrate); + return -1; + } + + frame = mbus_frame_new(MBUS_FRAME_TYPE_CONTROL); + + if (frame == NULL) + { + MBUS_ERROR("%s: failed to allocate mbus frame.\n", __PRETTY_FUNCTION__); + return -1; + } + + frame->control = MBUS_CONTROL_MASK_SND_UD | MBUS_CONTROL_MASK_DIR_M2S; + frame->address = address; + frame->control_information = control_information; + + if (mbus_send_frame(handle, frame) == -1) + { + MBUS_ERROR("%s: failed to send mbus frame.\n", __PRETTY_FUNCTION__); + retval = -1; + } + + mbus_frame_free(frame); + return retval; +} + //------------------------------------------------------------------------------ // send a request packet to from master to slave //------------------------------------------------------------------------------ diff --git a/mbus/mbus-protocol-aux.h b/mbus/mbus-protocol-aux.h index 9981362..a9afcad 100644 --- a/mbus/mbus-protocol-aux.h +++ b/mbus/mbus-protocol-aux.h @@ -186,6 +186,17 @@ int mbus_send_frame(mbus_handle * handle, mbus_frame *frame); */ int mbus_send_select_frame(mbus_handle * handle, const char *secondary_addr_str); +/** + * Sends switch baudrate frame using "unified" handle + * + * @param handle Initialized handle + * @param address Address (0-255) + * @param baudrate Baudrate (300,600,1200,2400,4800,9600,19200,38400) + * + * @return Zero when successful. + */ +int mbus_send_switch_baudrate_frame(mbus_handle * handle, int address, int baudrate); + /** * Sends data request frame to given slave using "unified" handle *