libebus project merged into ebusd project.
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
/INSTALL
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
Makefile
|
||||
Makefile.in
|
||||
/build/*
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
|
||||
+8
-31
@@ -1,32 +1,9 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
AM_CXXFLAGS = $(LIBEBUS_CFLAGS) -I$(top_srcdir)/lib -fpic -Wall -Wextra
|
||||
|
||||
bin_PROGRAMS = ebusd \
|
||||
ebusctl
|
||||
|
||||
ebusd_SOURCES = lib/appl.cpp \
|
||||
lib/daemon.cpp \
|
||||
lib/tcpsocket.cpp \
|
||||
lib/thread.cpp \
|
||||
lib/logger.cpp \
|
||||
src/connection.cpp \
|
||||
src/network.cpp \
|
||||
src/ebusloop.cpp \
|
||||
src/baseloop.cpp \
|
||||
src/main.cpp
|
||||
|
||||
ebusd_LDADD = $(LIBEBUS_LIBS) \
|
||||
-lpthread
|
||||
|
||||
dist_noinst_SCRIPTS = autogen.sh
|
||||
|
||||
|
||||
ebusctl_SOURCES = lib/appl.cpp \
|
||||
lib/tcpsocket.cpp \
|
||||
tools/ebusctl.cpp
|
||||
|
||||
ebusctl_LDADD = $(LIBEBUS_LIBS)
|
||||
SUBDIRS = src/libebus src/test src/libcore src/ebusd src/tools
|
||||
|
||||
distclean-local:
|
||||
-rm -rf autom4te.cache
|
||||
-rm -f aclocal.m4
|
||||
-rm -f config.h.in
|
||||
-rm -f configure
|
||||
-rm -f Makefile.in
|
||||
-rm -rf build
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
test -n "$srcdir" || srcdir=`dirname "$0"`
|
||||
test -n "$srcdir" || srcdir=.
|
||||
|
||||
mkdir -p "$srcdir/m4"
|
||||
mkdir -p "$srcdir/build"
|
||||
|
||||
autoreconf --force --install --verbose "$srcdir"
|
||||
|
||||
+14
-10
@@ -1,17 +1,21 @@
|
||||
AC_PREREQ([2.65])
|
||||
AC_INIT([ebusd], [0.4.0], [roland.jax@liwest.at], [ebusd], [https://github.com/yuhu-/ebusd])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/main.cpp])
|
||||
AC_CONFIG_AUX_DIR([build])
|
||||
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AC_PROG_CXX
|
||||
|
||||
PKG_CHECK_MODULES([LIBEBUS], [libebus-0.2 >= 0.2.0])
|
||||
AC_CONFIG_AUX_DIR([build])
|
||||
AC_CONFIG_SRCDIR([src/ebusd/main.cpp])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
src/libebus/Makefile
|
||||
src/test/Makefile
|
||||
src/libcore/Makefile
|
||||
src/ebusd/Makefile
|
||||
src/tools/Makefile])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign])
|
||||
|
||||
AM_PROG_AR
|
||||
AC_PROG_RANLIB
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
AM_CXXFLAGS = -fpic \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-I$(top_srcdir)/src/libcore \
|
||||
-I$(top_srcdir)/src/libebus
|
||||
|
||||
bin_PROGRAMS = ebusd
|
||||
|
||||
ebusd_SOURCES = connection.cpp \
|
||||
network.cpp \
|
||||
ebusloop.cpp \
|
||||
baseloop.cpp \
|
||||
main.cpp
|
||||
|
||||
ebusd_LDADD = $(top_srcdir)/src/libcore/libcore.a \
|
||||
$(top_srcdir)/src/libebus/libebus.a \
|
||||
-lpthread
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
-rm -rf .libs
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "baseloop.h"
|
||||
#include "configfile.h"
|
||||
#include "logger.h"
|
||||
#include "appl.h"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef BASELOOP_H_
|
||||
#define BASELOOP_H_
|
||||
|
||||
#include "libebus.h"
|
||||
#include "commands.h"
|
||||
#include "network.h"
|
||||
#include "ebusloop.h"
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
#include "tcpsocket.h"
|
||||
#include "wqueue.h"
|
||||
#include "message.h"
|
||||
#include "notify.h"
|
||||
#include "thread.h"
|
||||
#include "message.h"
|
||||
|
||||
class Connection : public Thread
|
||||
{
|
||||
@@ -20,7 +20,8 @@
|
||||
#ifndef EBUSLOOP_H_
|
||||
#define EBUSLOOP_H_
|
||||
|
||||
#include "libebus.h"
|
||||
#include "bus.h"
|
||||
#include "commands.h"
|
||||
#include "wqueue.h"
|
||||
#include "thread.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "libebus.h"
|
||||
#include "logger.h"
|
||||
#include "daemon.h"
|
||||
#include "appl.h"
|
||||
@@ -0,0 +1,14 @@
|
||||
AM_CXXFLAGS = -fpic \
|
||||
-Wall \
|
||||
-Wextra
|
||||
|
||||
noinst_LIBRARIES = libcore.a
|
||||
|
||||
libcore_a_SOURCES = appl.cpp \
|
||||
daemon.cpp \
|
||||
logger.cpp \
|
||||
thread.cpp \
|
||||
tcpsocket.cpp
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
@@ -0,0 +1,19 @@
|
||||
AM_CXXFLAGS = -fpic \
|
||||
-Wall \
|
||||
-Wextra
|
||||
|
||||
noinst_LIBRARIES = libebus.a
|
||||
|
||||
libebus_a_SOURCES = result.cpp \
|
||||
symbol.cpp \
|
||||
port.cpp \
|
||||
bus.cpp \
|
||||
command.cpp \
|
||||
commands.cpp \
|
||||
configfile.cpp \
|
||||
dump.cpp \
|
||||
decode.cpp \
|
||||
encode.cpp
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "bus.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
BusCommand::BusCommand(const std::string commandStr, const bool isPoll)
|
||||
: m_isPoll(isPoll), m_command(commandStr), m_resultCode(RESULT_OK)
|
||||
{
|
||||
unsigned char dstAddress = m_command[1];
|
||||
|
||||
if (dstAddress == BROADCAST)
|
||||
m_type = broadcast;
|
||||
else if (isMaster(dstAddress) == true)
|
||||
m_type = masterMaster;
|
||||
else
|
||||
m_type = masterSlave;
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
pthread_cond_init(&m_cond, NULL);
|
||||
}
|
||||
|
||||
BusCommand::~BusCommand()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
pthread_cond_destroy(&m_cond);
|
||||
}
|
||||
|
||||
const char* BusCommand::getResultCodeCStr()
|
||||
{
|
||||
return libebus::getResultCodeCStr(m_resultCode);
|
||||
}
|
||||
|
||||
const std::string BusCommand::getMessageStr()
|
||||
{
|
||||
std::string result;
|
||||
|
||||
if (m_resultCode >= 0) {
|
||||
if (m_type == masterSlave) {
|
||||
result = m_command.getDataStr(true);
|
||||
result += "00";
|
||||
result += m_result.getDataStr();
|
||||
result += "00";
|
||||
} else {
|
||||
result = "success";
|
||||
}
|
||||
}
|
||||
else
|
||||
result = "error";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Bus::Bus(const std::string deviceName, const bool noDeviceCheck, const long recvTimeout,
|
||||
const std::string dumpFile, const long dumpSize, const bool dumpState)
|
||||
: m_previousEscape(false), m_recvTimeout(recvTimeout), m_dumpState(dumpState),
|
||||
m_busLocked(false), m_busPriorRetry(false)
|
||||
{
|
||||
m_port = new Port(deviceName, noDeviceCheck);
|
||||
m_dump = new Dump(dumpFile, dumpSize);
|
||||
}
|
||||
|
||||
Bus::~Bus()
|
||||
{
|
||||
if (isConnected() == true)
|
||||
disconnect();
|
||||
|
||||
delete m_port;
|
||||
delete m_dump;
|
||||
}
|
||||
|
||||
void Bus::printBytes() const
|
||||
{
|
||||
unsigned char byte;
|
||||
ssize_t bytes_read;
|
||||
|
||||
bytes_read = m_port->recv(0);
|
||||
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
byte = m_port->byte();
|
||||
std::cout << std::nouppercase << std::hex << std::setw(2)
|
||||
<< std::setfill('0') << static_cast<unsigned>(byte);
|
||||
if (byte == SYN)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int Bus::proceed()
|
||||
{
|
||||
unsigned char byte_recv;
|
||||
ssize_t bytes_recv;
|
||||
|
||||
// fetch new message and get bus
|
||||
if (m_sendBuffer.size() != 0 && m_sstr.size() == 0) {
|
||||
BusCommand* busCommand = m_sendBuffer.front();
|
||||
return getBus(busCommand->getCommand()[0]);
|
||||
}
|
||||
|
||||
// wait for new data
|
||||
bytes_recv = m_port->recv(0);
|
||||
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_DEVICE;
|
||||
|
||||
for (int i = 0; i < bytes_recv; i++) {
|
||||
|
||||
// fetch next byte
|
||||
byte_recv = recvByte();
|
||||
|
||||
// store byte
|
||||
return proceedCycData(byte_recv); // TODO what if more than one byte was received?
|
||||
}
|
||||
|
||||
return RESULT_SYN;
|
||||
}
|
||||
|
||||
int Bus::proceedCycData(const unsigned char byte)
|
||||
{
|
||||
if (byte != SYN) {
|
||||
m_sstr.push_back_unescape(byte, m_previousEscape, false);
|
||||
if (m_busLocked == true)
|
||||
m_busLocked = false;
|
||||
|
||||
return RESULT_DATA;
|
||||
}
|
||||
|
||||
m_previousEscape = false;
|
||||
if (byte == SYN && m_sstr.size() != 0) {
|
||||
// lock bus after SYN-BYTE-SYN Sequence
|
||||
if (m_sstr.size() == 1 && m_busPriorRetry == false)
|
||||
m_busLocked = true;
|
||||
|
||||
m_cycBuffer.push(m_sstr);
|
||||
m_sstr.clear();
|
||||
|
||||
if (m_busLocked == true)
|
||||
return RESULT_BUS_LOCKED;
|
||||
}
|
||||
|
||||
return RESULT_SYN;
|
||||
}
|
||||
|
||||
SymbolString Bus::getCycData()
|
||||
{
|
||||
SymbolString data;
|
||||
|
||||
if (m_cycBuffer.empty() == false) {
|
||||
data = m_cycBuffer.front();
|
||||
m_cycBuffer.pop();
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int Bus::getBus(const unsigned char byte_sent)
|
||||
{
|
||||
unsigned char byte_recv;
|
||||
ssize_t bytes_sent, bytes_recv;
|
||||
|
||||
// send QQ
|
||||
bytes_sent = m_port->send(&byte_sent, 1);
|
||||
if (bytes_sent <= 0)
|
||||
return RESULT_ERR_SEND;
|
||||
|
||||
// receive 1 byte - must be QQ
|
||||
bytes_recv = m_port->recv(0, 1);
|
||||
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_DEVICE;
|
||||
|
||||
// fetch next byte
|
||||
byte_recv = recvByte();
|
||||
|
||||
// compare sent and received byte
|
||||
if (bytes_recv == 1 && byte_sent == byte_recv) {
|
||||
m_busPriorRetry = false;
|
||||
return RESULT_BUS_ACQUIRED;
|
||||
}
|
||||
|
||||
// store byte
|
||||
int ret = proceedCycData(byte_recv);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
// TODO this needs to be re-designed with above proceedCycData()
|
||||
// compare prior nibble for retry
|
||||
if (bytes_recv == 1 && (byte_sent & 0x0F) == (byte_recv & 0x0F)) {
|
||||
m_busPriorRetry = true;
|
||||
return RESULT_BUS_PRIOR_RETRY;
|
||||
}
|
||||
|
||||
m_busLocked = true;
|
||||
return RESULT_ERR_BUS_LOST;
|
||||
}
|
||||
|
||||
BusCommand* Bus::sendCommand()
|
||||
{
|
||||
unsigned char byte_recv;
|
||||
ssize_t bytes_recv;
|
||||
std::string result;
|
||||
SymbolString slaveData;
|
||||
int retval = RESULT_OK;
|
||||
|
||||
BusCommand* busCommand = m_sendBuffer.front();
|
||||
m_sendBuffer.pop();
|
||||
|
||||
// send ZZ PB SB NN Dx CRC
|
||||
SymbolString command = busCommand->getCommand();
|
||||
for (size_t i = 1; i < command.size(); i++) {
|
||||
retval = sendByte(command[i]);
|
||||
if (retval < 0)
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// BC -> send SYN
|
||||
if (busCommand->getType() == broadcast) {
|
||||
sendByte(SYN);
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// receive ACK
|
||||
bytes_recv = m_port->recv(m_recvTimeout);
|
||||
if (bytes_recv > 1) {
|
||||
retval = RESULT_ERR_EXTRA_DATA;
|
||||
goto on_exit;
|
||||
} else if (bytes_recv < 0) {
|
||||
retval = RESULT_ERR_TIMEOUT;
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
byte_recv = recvByte();
|
||||
|
||||
// is received byte SYN?
|
||||
if (byte_recv == SYN) {
|
||||
retval = RESULT_ERR_SYN;
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// is slave ACK negative?
|
||||
if (byte_recv == NAK) {
|
||||
|
||||
// send QQ ZZ PB SB NN Dx CRC again
|
||||
for (size_t i = 0; i < command.size(); i++) {
|
||||
retval = sendByte(command[i]);
|
||||
if (retval < 0)
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// receive ACK
|
||||
bytes_recv = m_port->recv(m_recvTimeout);
|
||||
if (bytes_recv > 1) {
|
||||
retval = RESULT_ERR_EXTRA_DATA;
|
||||
goto on_exit;
|
||||
} else if (bytes_recv < 0) {
|
||||
retval = RESULT_ERR_TIMEOUT;
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
byte_recv = recvByte();
|
||||
|
||||
// is received byte SYN?
|
||||
if (byte_recv == SYN) {
|
||||
retval = RESULT_ERR_SYN;
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// is slave ACK negative?
|
||||
if (byte_recv == NAK) {
|
||||
retval = sendByte(SYN);
|
||||
if (retval == 0)
|
||||
retval = RESULT_ERR_NAK;
|
||||
|
||||
goto on_exit;
|
||||
}
|
||||
}
|
||||
|
||||
// MM -> send SYN
|
||||
if (busCommand->getType() == masterMaster) {
|
||||
sendByte(SYN);
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// receive NN, Dx, CRC
|
||||
retval = recvSlaveDataAndCRC(slaveData);
|
||||
|
||||
// are calculated and received CRC equal?
|
||||
if (retval == RESULT_ERR_CRC) {
|
||||
|
||||
// send NAK
|
||||
retval = sendByte(NAK);
|
||||
if (retval < 0)
|
||||
goto on_exit;
|
||||
|
||||
// receive NN, Dx, CRC
|
||||
slaveData = SymbolString();
|
||||
retval = recvSlaveDataAndCRC(slaveData);
|
||||
|
||||
// are calculated and received CRC equal?
|
||||
if (retval == RESULT_ERR_CRC) {
|
||||
|
||||
// send NAK
|
||||
retval = sendByte(NAK);
|
||||
if (retval >= 0)
|
||||
retval = RESULT_ERR_CRC;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval < 0)
|
||||
goto on_exit;
|
||||
|
||||
// send ACK
|
||||
retval = sendByte(ACK);
|
||||
if (retval == -1) {
|
||||
retval = RESULT_ERR_ACK;
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
// MS -> send SYN
|
||||
sendByte(SYN);
|
||||
|
||||
on_exit:
|
||||
|
||||
// empty receive buffer
|
||||
while (m_port->size() != 0)
|
||||
byte_recv = recvByte();
|
||||
|
||||
busCommand->setResult(slaveData, retval);
|
||||
return busCommand;
|
||||
|
||||
}
|
||||
|
||||
BusCommand* Bus::delCommand()
|
||||
{
|
||||
BusCommand* busCommand = m_sendBuffer.front();
|
||||
m_sendBuffer.pop();
|
||||
|
||||
busCommand->setResult(SymbolString(), RESULT_ERR_BUS_LOST);
|
||||
return busCommand;
|
||||
}
|
||||
|
||||
int Bus::sendByte(const unsigned char byte_sent)
|
||||
{
|
||||
unsigned char byte_recv;
|
||||
ssize_t bytes_sent, bytes_recv;
|
||||
|
||||
bytes_sent = m_port->send(&byte_sent, 1);
|
||||
|
||||
// receive 1 byte - must be equal
|
||||
bytes_recv = m_port->recv(RECV_TIMEOUT);
|
||||
if (bytes_sent != bytes_recv)
|
||||
return RESULT_ERR_EXTRA_DATA;
|
||||
|
||||
byte_recv = recvByte();
|
||||
|
||||
if (byte_sent != byte_recv)
|
||||
return RESULT_ERR_SEND;
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
unsigned char Bus::recvByte()
|
||||
{
|
||||
unsigned char byte_recv;
|
||||
|
||||
// fetch byte
|
||||
byte_recv = m_port->byte();
|
||||
|
||||
if (m_dumpState == true)
|
||||
m_dump->write((const char*) &byte_recv);
|
||||
|
||||
return byte_recv;
|
||||
}
|
||||
|
||||
int Bus::recvSlaveDataAndCRC(SymbolString& result)
|
||||
{
|
||||
unsigned char byte_recv;
|
||||
ssize_t bytes_recv;
|
||||
bool previousEscape = false;
|
||||
|
||||
// receive NN
|
||||
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_TIMEOUT;
|
||||
|
||||
byte_recv = recvByte();
|
||||
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
|
||||
if (previousEscape == true && byte_recv == 0)
|
||||
return RESULT_ERR_ESC;
|
||||
|
||||
// escape sequence: get another symbol to find NN
|
||||
if (previousEscape == true) {
|
||||
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_TIMEOUT;
|
||||
|
||||
byte_recv = recvByte();
|
||||
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
|
||||
if (previousEscape == true)
|
||||
return RESULT_ERR_ESC;
|
||||
}
|
||||
|
||||
int NN = byte_recv;
|
||||
|
||||
// receive Dx
|
||||
for (int i = 0; i < NN; i++) {
|
||||
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_TIMEOUT;
|
||||
|
||||
byte_recv = recvByte();
|
||||
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
|
||||
if (previousEscape == true && byte_recv == 0)
|
||||
return RESULT_ERR_ESC;
|
||||
|
||||
// escape sequence: increase NN
|
||||
if (previousEscape == true)
|
||||
NN++;
|
||||
}
|
||||
if (previousEscape == true)
|
||||
return RESULT_ERR_ESC;
|
||||
|
||||
unsigned char crc_calc = result.getCRC();
|
||||
// receive CRC
|
||||
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_TIMEOUT;
|
||||
|
||||
byte_recv = recvByte();
|
||||
byte_recv = result.push_back_unescape(byte_recv, previousEscape, false);
|
||||
if (previousEscape == true && byte_recv == 0)
|
||||
return RESULT_ERR_ESC;
|
||||
|
||||
// escape sequence: get another symbol to find CRC
|
||||
if (previousEscape == true) {
|
||||
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
|
||||
if (bytes_recv < 0)
|
||||
return RESULT_ERR_TIMEOUT;
|
||||
|
||||
byte_recv = recvByte();
|
||||
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
|
||||
if (previousEscape == true)
|
||||
return RESULT_ERR_ESC;
|
||||
}
|
||||
|
||||
if (crc_calc != byte_recv)
|
||||
return RESULT_ERR_CRC;
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_BUS_H_
|
||||
#define LIBEBUS_BUS_H_
|
||||
|
||||
#include "symbol.h"
|
||||
#include "result.h"
|
||||
#include "port.h"
|
||||
#include "dump.h"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
// the maximum time allowed for retrieving a byte from an addressed slave
|
||||
#define RECV_TIMEOUT 10000
|
||||
|
||||
|
||||
enum CommandType { invalid, broadcast, masterMaster, masterSlave };
|
||||
|
||||
|
||||
class BusCommand
|
||||
{
|
||||
|
||||
public:
|
||||
BusCommand(const std::string commandStr, const bool isPoll);
|
||||
~BusCommand();
|
||||
|
||||
CommandType getType() const { return m_type; }
|
||||
bool isPoll() const { return m_isPoll; }
|
||||
SymbolString getCommand() const { return m_command; }
|
||||
bool isErrorResult() const { return m_resultCode < 0; }
|
||||
const char* getResultCodeCStr();
|
||||
SymbolString getResult() const { return m_result; }
|
||||
void setResult(const SymbolString result, const int resultCode) { m_result = result; m_resultCode = resultCode; }
|
||||
const std::string getMessageStr();
|
||||
void waitSignal() { pthread_cond_wait(&m_cond, &m_mutex); } // TODO timeout
|
||||
void sendSignal() { pthread_cond_signal(&m_cond); }
|
||||
|
||||
private:
|
||||
CommandType m_type;
|
||||
bool m_isPoll;
|
||||
SymbolString m_command;
|
||||
SymbolString m_result;
|
||||
int m_resultCode;
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_cond;
|
||||
};
|
||||
|
||||
class Bus
|
||||
{
|
||||
|
||||
public:
|
||||
Bus(const std::string deviceName, const bool noDeviceCheck, const long recvTimeout,
|
||||
const std::string dumpFile, const long dumpSize, const bool dumpState);
|
||||
~Bus();
|
||||
|
||||
void connect() { m_port->open(); }
|
||||
void disconnect() { if (m_port->isOpen() == true) m_port->close(); }
|
||||
bool isConnected() { return m_port->isOpen(); }
|
||||
|
||||
void printBytes() const;
|
||||
|
||||
int proceed();
|
||||
SymbolString getCycData();
|
||||
|
||||
void addCommand(BusCommand* busCommand) { m_sendBuffer.push(busCommand); }
|
||||
|
||||
int getBus(const unsigned char byte);
|
||||
BusCommand* sendCommand();
|
||||
BusCommand* delCommand();
|
||||
|
||||
void setDumpState(const bool dumpState) { m_dumpState = dumpState; }
|
||||
|
||||
private:
|
||||
Port* m_port;
|
||||
bool m_previousEscape;
|
||||
SymbolString m_sstr;
|
||||
std::queue<SymbolString> m_cycBuffer;
|
||||
std::queue<BusCommand*> m_sendBuffer;
|
||||
|
||||
const long m_recvTimeout;
|
||||
|
||||
Dump* m_dump;
|
||||
bool m_dumpState;
|
||||
|
||||
bool m_busLocked;
|
||||
bool m_busPriorRetry;
|
||||
|
||||
int proceedCycData(const unsigned char byte);
|
||||
int sendByte(const unsigned char byte_sent);
|
||||
unsigned char recvByte();
|
||||
int recvSlaveDataAndCRC(SymbolString& result);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_BUS_H_
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "command.h"
|
||||
#include "decode.h"
|
||||
#include "encode.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
std::string Command::calcData()
|
||||
{
|
||||
// encode - only first entry will be encoded
|
||||
// ToDo: if more parts are needed, they will be implemented
|
||||
encode(m_data, m_command[13], m_command[14]);
|
||||
|
||||
if (m_error.length() > 0)
|
||||
m_result = m_error;
|
||||
|
||||
return m_result;
|
||||
}
|
||||
|
||||
std::string Command::calcResult(const cmd_t& cmd)
|
||||
{
|
||||
int elements = strtol(m_command[9].c_str(), NULL, 10);
|
||||
|
||||
if (cmd.size() > 3) {
|
||||
bool found = false;
|
||||
|
||||
for (size_t i = 3; i < cmd.size(); i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < elements; j++) {
|
||||
if (m_command[10 + j*8] == cmd[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true) {
|
||||
found = false;
|
||||
|
||||
// decode
|
||||
calcSub(m_command[11 + j*8], m_command[12 + j*8],
|
||||
m_command[13 + j*8], m_command[14 + j*8]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
for (int j = 0; j < elements; j++) {
|
||||
|
||||
// decode
|
||||
calcSub(m_command[11 + j*8], m_command[12 + j*8],
|
||||
m_command[13 + j*8], m_command[14 + j*8]);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_error.length() > 0)
|
||||
m_result = m_error;
|
||||
|
||||
return m_result;
|
||||
}
|
||||
|
||||
void Command::calcSub(const std::string& part, const std::string& position,
|
||||
const std::string& type, const std::string& factor)
|
||||
{
|
||||
std::string data;
|
||||
|
||||
// Master Data
|
||||
if (strcasecmp(part.c_str(), "MD") == 0) {
|
||||
// QQ ZZ PB SB NN
|
||||
int md_pos = 10;
|
||||
int md_len = strtol(m_command[7].c_str(), NULL, 10)*2;
|
||||
data = m_data.substr(md_pos, md_len);
|
||||
}
|
||||
|
||||
// Slave Acknowledge
|
||||
else if (strcasecmp(part.c_str(), "SA") == 0) {
|
||||
// QQ ZZ PB SB NN + Dx + CRC
|
||||
int sa_pos = 10 + (strtol(m_command[7].c_str(), NULL, 10)*2) + 2;
|
||||
int sa_len = 2;
|
||||
data = m_data.substr(sa_pos, sa_len);
|
||||
}
|
||||
|
||||
// Slave Data
|
||||
else if (strcasecmp(part.c_str(), "SD") == 0) {
|
||||
// QQ ZZ PB SB NN + Dx + CRC ACK NN
|
||||
int sd_pos = 10 + (strtol(m_command[7].c_str(), NULL, 10)*2) + 6;
|
||||
int sd_len = m_data.length() - (10 + (strtol(m_command[7].c_str(), NULL, 10)*2) + 6) - 4;
|
||||
data = m_data.substr(sd_pos, sd_len);
|
||||
}
|
||||
|
||||
// Master Acknowledge
|
||||
else if (strcasecmp(part.c_str(), "MA") == 0) {
|
||||
// QQ ZZ PB SB NN + Dx + CRC ACK NN + Dx
|
||||
int ma_pos = m_data.length() - 2;
|
||||
int ma_len = 2;
|
||||
data = m_data.substr(ma_pos, ma_len);
|
||||
}
|
||||
|
||||
decode(data, position, type, factor);
|
||||
}
|
||||
|
||||
void Command::decode(const std::string& data, const std::string& position,
|
||||
const std::string& type, const std::string& factor)
|
||||
{
|
||||
std::ostringstream result, value;
|
||||
Decode* help = NULL;
|
||||
|
||||
// prepare position
|
||||
std::string token;
|
||||
std::istringstream stream(position);
|
||||
std::vector<int> pos;
|
||||
|
||||
while (std::getline(stream, token, ',') != 0)
|
||||
pos.push_back(strtol(token.c_str(), NULL, 10));
|
||||
|
||||
if (strcasecmp(type.c_str(), "HEX") == 0) {
|
||||
if (pos.size() <= 1 || pos[1] < pos[0])
|
||||
pos[1] = pos[0];
|
||||
|
||||
value << data.substr((pos[0]-1)*2, (pos[1]-pos[0]+1)*2);
|
||||
help = new DecodeHEX(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "UCH") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeUCH(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "SCH") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeSCH(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "UIN") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
|
||||
help = new DecodeUIN(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "SIN") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
|
||||
help = new DecodeSIN(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "ULG") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2)
|
||||
<< data.substr((pos[2]-1)*2, 2) << data.substr((pos[3]-1)*2, 2);
|
||||
help = new DecodeULG(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "SLG") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2)
|
||||
<< data.substr((pos[2]-1)*2, 2) << data.substr((pos[3]-1)*2, 2);
|
||||
help = new DecodeSLG(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "FLT") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
|
||||
help = new DecodeFLT(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "STR") == 0) {
|
||||
if (pos.size() <= 1 || pos[1] < pos[0])
|
||||
pos[1] = pos[0];
|
||||
|
||||
value << data.substr((pos[0]-1)*2, (pos[1]-pos[0]+1)*2);
|
||||
help = new DecodeSTR(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BCD") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeBCD(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D1B") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeD1B(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D1C") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeD1C(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D2B") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
|
||||
help = new DecodeD2B(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D2C") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
|
||||
help = new DecodeD2C(value.str(), factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BDA") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2)
|
||||
<< data.substr((pos[1]-1)*2, 2)
|
||||
<< data.substr((pos[2]-1)*2, 2);
|
||||
help = new DecodeBDA(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "HDA") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2)
|
||||
<< data.substr((pos[1]-1)*2, 2)
|
||||
<< data.substr((pos[2]-1)*2, 2);
|
||||
help = new DecodeHDA(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BTI") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2)
|
||||
<< data.substr((pos[1]-1)*2, 2)
|
||||
<< data.substr((pos[2]-1)*2, 2);
|
||||
help = new DecodeBTI(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "HTI") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2)
|
||||
<< data.substr((pos[1]-1)*2, 2)
|
||||
<< data.substr((pos[2]-1)*2, 2);
|
||||
help = new DecodeHTI(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BDY") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeBDY(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "HDY") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeHDY(value.str());
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "TTM") == 0) {
|
||||
value << data.substr((pos[0]-1)*2, 2);
|
||||
help = new DecodeTTM(value.str());
|
||||
}
|
||||
|
||||
if (help == NULL) {
|
||||
result << "type '" << type.c_str() << "' not implemented!";
|
||||
m_error = result.str();
|
||||
} else {
|
||||
result << help->decode();
|
||||
|
||||
if (m_result.length() > 0)
|
||||
m_result += " ";
|
||||
|
||||
m_result += result.str();
|
||||
}
|
||||
|
||||
delete help;
|
||||
}
|
||||
|
||||
void Command::encode(const std::string& data, const std::string& type,
|
||||
const std::string& factor)
|
||||
{
|
||||
std::ostringstream result;
|
||||
Encode* help = NULL;
|
||||
|
||||
if (strcasecmp(type.c_str(), "HEX") == 0) {
|
||||
help = new EncodeHEX(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "UCH") == 0) {
|
||||
help = new EncodeUCH(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "SCH") == 0) {
|
||||
help = new EncodeSCH(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "UIN") == 0) {
|
||||
help = new EncodeUIN(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "SIN") == 0) {
|
||||
help = new EncodeSIN(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "ULG") == 0) {
|
||||
help = new EncodeULG(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "SLG") == 0) {
|
||||
help = new EncodeSLG(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "FLT") == 0) {
|
||||
help = new EncodeSLG(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "STR") == 0) {
|
||||
help = new EncodeSTR(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BCD") == 0) {
|
||||
help = new EncodeBCD(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D1B") == 0) {
|
||||
help = new EncodeD1B(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D1C") == 0) {
|
||||
help = new EncodeD1C(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D2B") == 0) {
|
||||
help = new EncodeD2B(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "D2C") == 0) {
|
||||
help = new EncodeD2C(data, factor);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BDA") == 0) {
|
||||
help = new EncodeBDA(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "HDA") == 0) {
|
||||
help = new EncodeHDA(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BTI") == 0) {
|
||||
help = new EncodeBTI(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "HTI") == 0) {
|
||||
help = new EncodeHTI(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "BDY") == 0) {
|
||||
help = new EncodeBDY(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "HDY") == 0) {
|
||||
help = new EncodeHDY(data);
|
||||
}
|
||||
else if (strcasecmp(type.c_str(), "TTM") == 0) {
|
||||
help = new EncodeTTM(data);
|
||||
}
|
||||
|
||||
if (help == NULL) {
|
||||
result << "type '" << type.c_str() << "' not implemented!";
|
||||
m_error = result.str();
|
||||
} else {
|
||||
result << help->encode();
|
||||
|
||||
if (m_result.length() > 0)
|
||||
m_result += " ";
|
||||
|
||||
m_result += result.str();
|
||||
}
|
||||
|
||||
delete help;
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_COMMAND_H_
|
||||
#define LIBEBUS_COMMAND_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
typedef std::vector<std::string> cmd_t;
|
||||
typedef cmd_t::const_iterator cmdCI_t;
|
||||
|
||||
class Command
|
||||
{
|
||||
|
||||
public:
|
||||
Command(int index, cmd_t command) : m_index(index), m_command(command) {}
|
||||
Command(int index, cmd_t command, std::string data)
|
||||
: m_index(index), m_command(command), m_data(data) {}
|
||||
|
||||
cmd_t getCommand() const { return m_command; }
|
||||
void setData(const std::string& data) { m_data = data; }
|
||||
std::string getData() const { return m_data; }
|
||||
std::string calcData();
|
||||
|
||||
std::string calcResult(const cmd_t& cmd);
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
cmd_t m_command;
|
||||
std::string m_data;
|
||||
std::string m_result;
|
||||
std::string m_error;
|
||||
|
||||
void calcSub(const std::string& part, const std::string& position,
|
||||
const std::string& type, const std::string& factor);
|
||||
|
||||
void decode(const std::string& data, const std::string& position,
|
||||
const std::string& type, const std::string& factor);
|
||||
|
||||
void encode(const std::string& data, const std::string& type,
|
||||
const std::string& factor);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_COMMAND_H_
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "commands.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
Commands::~Commands()
|
||||
{
|
||||
for (mapCI_t iter = m_polDB.begin(); iter != m_polDB.end(); ++iter)
|
||||
delete iter->second;
|
||||
|
||||
m_polDB.clear();
|
||||
|
||||
for (mapCI_t iter = m_cycDB.begin(); iter != m_cycDB.end(); ++iter)
|
||||
delete iter->second;
|
||||
|
||||
m_cycDB.clear();
|
||||
|
||||
m_cmdDB.clear();
|
||||
}
|
||||
|
||||
void Commands::addCommand(const cmd_t& command)
|
||||
{
|
||||
m_cmdDB.push_back(command);
|
||||
|
||||
if (strcasecmp(command[0].c_str(),"C") == 0) {
|
||||
Command* cmd = new Command(m_cmdDB.size()-1, command);
|
||||
m_cycDB.insert(pair_t(m_cmdDB.size()-1, cmd));
|
||||
}
|
||||
|
||||
if (strcasecmp(command[0].c_str(),"P") == 0) {
|
||||
Command* cmd = new Command(m_cmdDB.size()-1, command);
|
||||
m_polDB.insert(pair_t(m_cmdDB.size()-1, cmd));
|
||||
}
|
||||
}
|
||||
|
||||
void Commands::printCommands() const
|
||||
{
|
||||
if (m_cmdDB.size() == 0)
|
||||
return;
|
||||
|
||||
for (cmdDBCI_t i = m_cmdDB.begin(); i != m_cmdDB.end(); i++) {
|
||||
printCommand(*i);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int Commands::findCommand(const std::string& data) const
|
||||
{
|
||||
// no commands definend
|
||||
if (m_cmdDB.size() == 0)
|
||||
return -2;
|
||||
|
||||
// preapre string for searching command
|
||||
std::string token;
|
||||
std::istringstream isstr(data);
|
||||
std::vector<std::string> cmd;
|
||||
|
||||
// split stream
|
||||
while (std::getline(isstr, token, ' ') != 0)
|
||||
cmd.push_back(token);
|
||||
|
||||
std::size_t index;
|
||||
cmdDBCI_t i = m_cmdDB.begin();
|
||||
|
||||
// walk through commands - GET
|
||||
if (strcasecmp(cmd[0].c_str(), "GET") == 0) {
|
||||
for (index = 0; i != m_cmdDB.end(); i++, index++) {
|
||||
|
||||
// empty line
|
||||
if ((*i).size() == 0)
|
||||
continue;
|
||||
|
||||
if (((strcasecmp((*i)[0].c_str(), "R") == 0)
|
||||
|| (strcasecmp((*i)[0].c_str(), "P") == 0))
|
||||
&& (strcasecmp((*i)[1].c_str(), cmd[1].c_str()) == 0)
|
||||
&& (strcasecmp((*i)[2].c_str(), cmd[2].c_str()) == 0))
|
||||
return index;
|
||||
}
|
||||
// walk through commands - SET, CYC
|
||||
} else {
|
||||
// correct type
|
||||
if (strcasecmp(cmd[0].c_str(), "SET") == 0)
|
||||
cmd[0] = "W";
|
||||
else if (strcasecmp(cmd[0].c_str(), "CYC") == 0)
|
||||
cmd[0] = "C";
|
||||
|
||||
for (index = 0; i != m_cmdDB.end(); i++, index++) {
|
||||
|
||||
// empty line
|
||||
if ((*i).size() == 0)
|
||||
continue;
|
||||
|
||||
if (strcasecmp((*i)[0].c_str(), cmd[0].c_str()) == 0 &&
|
||||
strcasecmp((*i)[1].c_str(), cmd[1].c_str()) == 0 &&
|
||||
strcasecmp((*i)[2].c_str(), cmd[2].c_str()) == 0)
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
// command not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string Commands::getEbusCommand(const int index) const
|
||||
{
|
||||
cmd_t command = m_cmdDB.at(index);
|
||||
std::string cmd(command[5]);
|
||||
cmd += command[6];
|
||||
std::stringstream sstr;
|
||||
sstr << std::setw(2) << std::hex << std::setfill('0') << command[7];
|
||||
cmd += sstr.str();
|
||||
cmd += command[8];
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
int Commands::storeCycData(const std::string& data) const
|
||||
{
|
||||
// no commands defined
|
||||
if (m_cycDB.size() == 0)
|
||||
return -2;
|
||||
|
||||
// search skipped - string too short
|
||||
if (data.length() < 10)
|
||||
return -3;
|
||||
|
||||
// prepare string for searching command
|
||||
std::string search(data.substr(2, 8 + strtol(data.substr(8,2).c_str(), NULL, 16) * 2));
|
||||
|
||||
mapCI_t iter = m_cycDB.begin();
|
||||
|
||||
// walk through commands
|
||||
for (; iter != m_cycDB.end(); iter++) {
|
||||
|
||||
std::string command = getEbusCommand(iter->first);
|
||||
|
||||
// skip wrong search string length
|
||||
if (command.length() > search.length())
|
||||
continue;
|
||||
|
||||
if (strcasecmp(command.c_str(), search.substr(0,command.length()).c_str()) == 0) {
|
||||
iter->second->setData(data);
|
||||
return iter->first;
|
||||
}
|
||||
}
|
||||
|
||||
// command not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string Commands::getCycData(int index) const
|
||||
{
|
||||
mapCI_t iter = m_cycDB.find(index);
|
||||
if (iter != m_cycDB.end())
|
||||
return iter->second->getData();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
int Commands::nextPolCommand()
|
||||
{
|
||||
size_t index = 0;
|
||||
|
||||
m_polIndex++;
|
||||
|
||||
if (m_polIndex == m_polDB.size())
|
||||
m_polIndex = 0;
|
||||
|
||||
mapCI_t iter = m_polDB.begin();
|
||||
|
||||
for (; iter != m_polDB.end(); iter++, index++)
|
||||
if (index == m_polIndex)
|
||||
return iter->first;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Commands::storePolData(const std::string& data) const
|
||||
{
|
||||
// prepare string for searching command
|
||||
std::string search(data.substr(2, 8 + strtol(data.substr(8,2).c_str(), NULL, 16) * 2));
|
||||
|
||||
mapCI_t iter = m_polDB.begin();
|
||||
|
||||
// walk through commands
|
||||
for (; iter != m_polDB.end(); iter++) {
|
||||
|
||||
std::string command = getEbusCommand(iter->first);
|
||||
|
||||
// skip wrong search string length
|
||||
if (command.length() > search.length())
|
||||
continue;
|
||||
|
||||
if (strcasecmp(command.c_str(), search.substr(0,command.length()).c_str()) == 0)
|
||||
iter->second->setData(data);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string Commands::getPolData(int index) const
|
||||
{
|
||||
mapCI_t iter = m_polDB.find(index);
|
||||
if (iter != m_polDB.end())
|
||||
return iter->second->getData();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
void Commands::printCommand(const cmd_t& command) const
|
||||
{
|
||||
if (command.size() == 0)
|
||||
return;
|
||||
|
||||
for (cmdCI_t i = command.begin(); i != command.end(); i++)
|
||||
std::cout << *i << ';';
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_COMMANDS_H_
|
||||
#define LIBEBUS_COMMANDS_H_
|
||||
|
||||
#include "command.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
typedef std::vector<cmd_t> cmdDB_t;
|
||||
typedef cmdDB_t::const_iterator cmdDBCI_t;
|
||||
|
||||
typedef std::map<int, Command*> map_t;
|
||||
typedef map_t::const_iterator mapCI_t;
|
||||
typedef std::pair<int, Command*> pair_t;
|
||||
|
||||
class Commands
|
||||
{
|
||||
|
||||
public:
|
||||
Commands() : m_polIndex(-1) {}
|
||||
~Commands();
|
||||
|
||||
void addCommand(const cmd_t& command);
|
||||
void printCommands() const;
|
||||
|
||||
std::size_t sizeCmdDB() const { return m_cmdDB.size(); }
|
||||
std::size_t sizeCycDB() const { return m_cycDB.size(); }
|
||||
std::size_t sizePolDB() const { return m_polDB.size(); }
|
||||
|
||||
cmd_t const& operator[](const std::size_t& index) const { return m_cmdDB[index]; }
|
||||
|
||||
int findCommand(const std::string& data) const;
|
||||
|
||||
std::string getCmdType(const int index) const { return std::string(m_cmdDB.at(index)[0]); }
|
||||
std::string getEbusType(const int index) const { return std::string(m_cmdDB.at(index)[4]); }
|
||||
std::string getEbusCommand(const int index) const;
|
||||
|
||||
int storeCycData(const std::string& data) const;
|
||||
std::string getCycData(int index) const;
|
||||
|
||||
int nextPolCommand();
|
||||
void storePolData(const std::string& data) const;
|
||||
std::string getPolData(int index) const;
|
||||
|
||||
private:
|
||||
cmdDB_t m_cmdDB;
|
||||
map_t m_cycDB;
|
||||
map_t m_polDB;
|
||||
size_t m_polIndex;
|
||||
|
||||
void printCommand(const cmd_t& command) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_COMMANDS_H_
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "configfile.h"
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <dirent.h>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
void ConfigFileCSV::readFile(std::istream& is, Commands& commands)
|
||||
{
|
||||
std::string line;
|
||||
|
||||
// read lines
|
||||
while (std::getline(is, line) != 0) {
|
||||
cmd_t row;
|
||||
std::string column;
|
||||
|
||||
std::istringstream isstr(line);
|
||||
|
||||
// walk through columns
|
||||
while (std::getline(isstr, column, ';') != 0)
|
||||
row.push_back(column);
|
||||
|
||||
// skip empty and commented rows
|
||||
if (row.empty() == true || row[0][0] == '#')
|
||||
continue;
|
||||
|
||||
commands.addCommand(row);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ConfigFileXML::readFile(std::istream& is, Commands& commands)
|
||||
{
|
||||
; // ToDo: Implamantion for xml files
|
||||
}
|
||||
|
||||
|
||||
|
||||
ConfigCommands::ConfigCommands(const std::string path, const FileType type)
|
||||
{
|
||||
m_path = path;
|
||||
m_configfile = NULL;
|
||||
setType(type);
|
||||
addFiles(m_path, m_extension);
|
||||
}
|
||||
|
||||
void ConfigCommands::setType(const FileType type)
|
||||
{
|
||||
if (m_configfile != NULL)
|
||||
delete m_configfile;
|
||||
|
||||
switch (type) {
|
||||
case CSV:
|
||||
m_configfile = new ConfigFileCSV();
|
||||
m_extension = "csv";
|
||||
break;
|
||||
case XML:
|
||||
m_configfile = new ConfigFileXML();
|
||||
m_extension = "xml";
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
Commands* ConfigCommands::getCommands()
|
||||
{
|
||||
Commands* commands = new Commands();
|
||||
std::vector<std::string>::const_iterator i = m_files.begin();
|
||||
|
||||
for(; i != m_files.end(); i++) {
|
||||
std::fstream file((*i).c_str(), std::ios::in);
|
||||
|
||||
if(file.is_open() == true) {
|
||||
m_configfile->readFile(file, *commands);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
};
|
||||
|
||||
void ConfigCommands::addFiles(const std::string path, const std::string extension)
|
||||
{
|
||||
DIR* dir = opendir(path.c_str());
|
||||
|
||||
if (dir == NULL)
|
||||
return;
|
||||
|
||||
dirent* d = readdir(dir);
|
||||
|
||||
while (d != NULL) {
|
||||
|
||||
if (d->d_type == DT_DIR) {
|
||||
std::string fn = d->d_name;
|
||||
|
||||
if (fn != "." && fn != "..") {
|
||||
const std::string p = path + "/" + d->d_name;
|
||||
addFiles(p, extension);
|
||||
}
|
||||
|
||||
} else if (d->d_type == DT_REG) {
|
||||
std::string fn = d->d_name;
|
||||
|
||||
if (fn.find(extension, (fn.length() - extension.length())) != std::string::npos) {
|
||||
const std::string p = path + "/" + d->d_name;
|
||||
m_files.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
d = readdir(dir);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_CONFIGFILE_H_
|
||||
#define LIBEBUS_CONFIGFILE_H_
|
||||
|
||||
#include "commands.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
enum FileType { CSV, XML };
|
||||
|
||||
class ConfigFile
|
||||
{
|
||||
|
||||
public:
|
||||
virtual ~ConfigFile() {}
|
||||
|
||||
virtual void readFile(std::istream& is, Commands& commands) = 0;
|
||||
|
||||
};
|
||||
|
||||
class ConfigFileCSV : public ConfigFile
|
||||
{
|
||||
|
||||
public:
|
||||
~ConfigFileCSV() {}
|
||||
|
||||
void readFile(std::istream& is, Commands& commands);
|
||||
|
||||
};
|
||||
|
||||
class ConfigFileXML : public ConfigFile
|
||||
{
|
||||
|
||||
public:
|
||||
~ConfigFileXML() {}
|
||||
|
||||
void readFile(std::istream& is, Commands& commands);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ConfigCommands
|
||||
{
|
||||
|
||||
public:
|
||||
ConfigCommands(const std::string path, const FileType type);
|
||||
~ConfigCommands() { delete m_configfile; }
|
||||
|
||||
void setType(const FileType type);
|
||||
Commands* getCommands();
|
||||
|
||||
private:
|
||||
ConfigFile* m_configfile;
|
||||
std::string m_path;
|
||||
std::string m_extension;
|
||||
std::vector<std::string> m_files;
|
||||
|
||||
void addFiles(const std::string path, const std::string extension);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_CONFIGFILE_H_
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "decode.h"
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
Decode::Decode(const std::string& data, const std::string& factor)
|
||||
: m_data(data)
|
||||
{
|
||||
if ((factor.find_first_not_of("0123456789.") == std::string::npos) == true)
|
||||
m_factor = static_cast<float>(strtod(factor.c_str(), NULL));
|
||||
else
|
||||
m_factor = 1.0;
|
||||
}
|
||||
|
||||
|
||||
std::string DecodeHEX::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
|
||||
for (size_t i = 0; i < m_data.length()/2; i++)
|
||||
result << m_data.substr(i*2, 2) << " ";
|
||||
|
||||
return result.str().substr(0, result.str().length()-1);
|
||||
}
|
||||
|
||||
std::string DecodeUCH::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
unsigned short x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setprecision(3) << std::fixed << static_cast<float>(x * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeSCH::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
unsigned short x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
if ((x & 0x80) == 0x80)
|
||||
result << std::setprecision(3) << std::fixed
|
||||
<< static_cast<float>(static_cast<short>(- ( ((unsigned char) (~ x)) + 1) ) * m_factor);
|
||||
else
|
||||
result << std::setprecision(3) << std::fixed
|
||||
<< static_cast<float>(static_cast<short>(x) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeUIN::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
unsigned short x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setprecision(3) << std::fixed << static_cast<float>(x * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeSIN::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
unsigned short x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setprecision(3) << std::fixed << static_cast<float>(static_cast<short>(x) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeULG::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
unsigned int x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setprecision(3) << std::fixed << static_cast<float>(x * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeSLG::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
unsigned int x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setprecision(3) << std::fixed <<static_cast<float>(static_cast<int>(x) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeFLT::decode()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << m_data;
|
||||
|
||||
short x;
|
||||
ss >> x;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setprecision(3) << std::fixed << static_cast<float>(x / 1000.0 * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeSTR::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
|
||||
for (size_t i = 0; i <= m_data.length()/2; i++) {
|
||||
char tmp = static_cast<char>(strtol(m_data.substr(i*2, 2).c_str(), NULL, 16));
|
||||
if (tmp == 0x00) tmp = 0x20;
|
||||
result << tmp;
|
||||
}
|
||||
|
||||
return result.str().substr(0, result.str().length()-1);
|
||||
}
|
||||
|
||||
std::string DecodeBCD::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned char src = strtol(m_data.c_str(), NULL, 16);
|
||||
|
||||
if ((src & 0x0F) > 0x09 || ((src >> 4) & 0x0F) > 0x09)
|
||||
result << static_cast<short>(0xFF);
|
||||
else
|
||||
result << static_cast<short>(( ( ((src & 0xF0) >> 4) * 10) + (src & 0x0F) ) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeD1B::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned char src = strtol(m_data.c_str(), NULL, 16);
|
||||
|
||||
if ((src & 0x80) == 0x80)
|
||||
result << static_cast<short>((- ( ((unsigned char) (~ src)) + 1) ) * m_factor);
|
||||
else
|
||||
result << static_cast<short>(src * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeD1C::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned char src = strtol(m_data.c_str(), NULL, 16);
|
||||
|
||||
if (src > 0xC8)
|
||||
result << static_cast<float>(0xFF);
|
||||
else
|
||||
result << static_cast<float>((src / 2.0) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeD2B::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned char src_lsb = static_cast<char>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
|
||||
unsigned char src_msb = static_cast<char>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
|
||||
|
||||
if ((src_msb & 0x80) == 0x80)
|
||||
result << static_cast<float>
|
||||
((- ( ((unsigned char) (~ src_msb)) +
|
||||
( ( ((unsigned char) (~ src_lsb)) + 1) / 256.0) ) ) * m_factor);
|
||||
|
||||
else
|
||||
result << static_cast<float>((src_msb + (src_lsb / 256.0)) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeD2C::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned char src_lsb = static_cast<char>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
|
||||
unsigned char src_msb = static_cast<char>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
|
||||
|
||||
if ((src_msb & 0x80) == 0x80)
|
||||
result << static_cast<float>
|
||||
((- ( ( ( ((unsigned char) (~ src_msb)) * 16.0) ) +
|
||||
( ( ((unsigned char) (~ src_lsb)) & 0xF0) >> 4) +
|
||||
( ( ( ((unsigned char) (~ src_lsb)) & 0x0F) +1 ) / 16.0) ) ) * m_factor);
|
||||
|
||||
else
|
||||
result << static_cast<float>(( (src_msb * 16.0) + ((src_lsb & 0xF0) >> 4) +
|
||||
((src_lsb & 0x0F) / 16.0) ) * m_factor);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeBDA::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
Decode* decode;
|
||||
short array[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
decode = new DecodeBCD(m_data.substr(i*2, 2), "1.0");
|
||||
array[i] = static_cast<short>(strtol(decode->decode().c_str(), NULL, 10));
|
||||
delete decode;
|
||||
}
|
||||
|
||||
result << std::setw(2) << std::setfill('0') << array[0] << "."
|
||||
<< std::setw(2) << std::setfill('0') << array[1] << "."
|
||||
<< array[2] + 2000;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeHDA::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short dd = static_cast<short>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
|
||||
short mm = static_cast<short>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
|
||||
short yy = static_cast<short>(strtol(m_data.substr(4, 2).c_str(), NULL, 16));
|
||||
|
||||
result << std::setw(2) << std::setfill('0') << dd << "."
|
||||
<< std::setw(2) << std::setfill('0') << mm << "."
|
||||
<< yy + 2000;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeBTI::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
Decode* decode;
|
||||
short array[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
decode = new DecodeBCD(m_data.substr(i*2, 2), "1.0");
|
||||
array[i] = static_cast<short>(strtol(decode->decode().c_str(), NULL, 10));
|
||||
delete decode;
|
||||
}
|
||||
|
||||
result << std::setw(2) << std::setfill('0') << array[0] << ":"
|
||||
<< std::setw(2) << std::setfill('0') << array[1] << ":"
|
||||
<< std::setw(2) << std::setfill('0') << array[2];
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeHTI::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short hh = static_cast<short>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
|
||||
short mm = static_cast<short>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
|
||||
short ss = static_cast<short>(strtol(m_data.substr(4, 2).c_str(), NULL, 16));
|
||||
|
||||
result << std::setw(2) << std::setfill('0') << hh << ":"
|
||||
<< std::setw(2) << std::setfill('0') << mm << ":"
|
||||
<< std::setw(2) << std::setfill('0') << ss;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeBDY::decode()
|
||||
{
|
||||
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
|
||||
|
||||
std::ostringstream result;
|
||||
short day = static_cast<short>(strtol(m_data.c_str(), NULL, 16));
|
||||
|
||||
if (day < 0 || day > 6)
|
||||
day = 7;
|
||||
|
||||
result << days[day];
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeHDY::decode()
|
||||
{
|
||||
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
|
||||
|
||||
std::ostringstream result;
|
||||
short day = static_cast<short>(strtol(m_data.c_str(), NULL, 16)) - 1;
|
||||
|
||||
if (day < 0 || day > 6)
|
||||
day = 7;
|
||||
|
||||
result << days[day];
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string DecodeTTM::decode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short hh = static_cast<short>(strtol(m_data.c_str(), NULL, 16)) / 6;
|
||||
short mm = static_cast<short>(strtol(m_data.c_str(), NULL, 16)) % 6 * 10;
|
||||
|
||||
result << std::setw(2) << std::setfill('0') << hh << ":"
|
||||
<< std::setw(2) << std::setfill('0') << mm;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_DECODE_H_
|
||||
#define LIBEBUS_DECODE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
class Decode
|
||||
{
|
||||
|
||||
public:
|
||||
Decode(const std::string& data, const std::string& factor = "");
|
||||
virtual ~Decode() {}
|
||||
|
||||
virtual std::string decode() = 0;
|
||||
|
||||
protected:
|
||||
std::string m_data;
|
||||
float m_factor;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class DecodeHEX : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeHEX(const std::string& data) : Decode(data) {}
|
||||
~DecodeHEX() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeUCH : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeUCH(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeUCH() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeSCH : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeSCH(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeSCH() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeUIN : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeUIN(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeUIN() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeSIN : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeSIN(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeSIN() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeULG : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeULG(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeULG() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeSLG : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeSLG(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeSLG() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeFLT : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeFLT(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeFLT() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeSTR : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeSTR(std::string data) : Decode(data) {}
|
||||
~DecodeSTR() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeBCD : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeBCD(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeBCD() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeD1B : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeD1B(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeD1B() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeD1C : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeD1C(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeD1C() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeD2B : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeD2B(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeD2B() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeD2C : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeD2C(const std::string& data, const std::string& factor)
|
||||
: Decode(data, factor) {}
|
||||
~DecodeD2C() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeBDA : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeBDA(const std::string& data) : Decode(data) {}
|
||||
~DecodeBDA() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeHDA : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeHDA(const std::string& data) : Decode(data) {}
|
||||
~DecodeHDA() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeBTI : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeBTI(const std::string& data) : Decode(data) {}
|
||||
~DecodeBTI() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeHTI : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeHTI(const std::string& data) : Decode(data) {}
|
||||
~DecodeHTI() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeBDY : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeBDY(const std::string& data) : Decode(data) {}
|
||||
~DecodeBDY() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeHDY : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeHDY(const std::string& data) : Decode(data) {}
|
||||
~DecodeHDY() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
class DecodeTTM : public Decode
|
||||
{
|
||||
|
||||
public:
|
||||
DecodeTTM(const std::string& data) : Decode(data) {}
|
||||
~DecodeTTM() {}
|
||||
|
||||
std::string decode();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_DECODE_H_
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "dump.h"
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
int Dump::write(const char* byte)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
std::ofstream fs(m_filename.c_str(), std::ios::out | std::ios::binary | std::ios::app);
|
||||
|
||||
if (fs == 0)
|
||||
return -1;
|
||||
|
||||
fs.write(byte, 1);
|
||||
|
||||
if (fs.tellp() >= m_filesize * 1024) {
|
||||
std::string oldfile;
|
||||
oldfile += m_filename;
|
||||
oldfile += ".old";
|
||||
ret = rename(m_filename.c_str(), oldfile.c_str());
|
||||
}
|
||||
|
||||
fs.close();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_DUMP_H_
|
||||
#define LIBEBUS_DUMP_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
class Dump
|
||||
{
|
||||
|
||||
public:
|
||||
Dump(std::string filename, long filesize)
|
||||
: m_filename(filename), m_filesize(filesize) {}
|
||||
|
||||
int write(const char* byte);
|
||||
|
||||
void setFilename(const std::string& filename) { m_filename = filename; }
|
||||
void setFilesize(const long filesize) { m_filesize = filesize; }
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
long m_filesize;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_DUMP_H_
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "encode.h"
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
Encode::Encode(const std::string& data, const std::string& factor)
|
||||
: m_data(data)
|
||||
{
|
||||
if ((factor.find_first_not_of("0123456789.") == std::string::npos) == true)
|
||||
m_factor = static_cast<float>(strtod(factor.c_str(), NULL));
|
||||
else
|
||||
m_factor = 1.0;
|
||||
}
|
||||
|
||||
|
||||
std::string EncodeHEX::encode()
|
||||
{
|
||||
m_data.erase(std::remove_if(m_data.begin(), m_data.end(), isspace), m_data.end());
|
||||
|
||||
return m_data;
|
||||
}
|
||||
|
||||
std::string EncodeUCH::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned short src = static_cast<unsigned short>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
result << std::setw(2) << std::hex << std::setfill('0') << src;
|
||||
|
||||
return result.str().substr(result.str().length()-2,2);
|
||||
}
|
||||
|
||||
std::string EncodeSCH::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
|
||||
if (src < -127 || src > 127)
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0x80);
|
||||
else
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(src);
|
||||
|
||||
return result.str().substr(result.str().length()-2,2);
|
||||
}
|
||||
|
||||
std::string EncodeUIN::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned short src = static_cast<unsigned short>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
result << std::setw(4) << std::hex << std::setfill('0') << src;
|
||||
|
||||
return result.str().substr(2,2) + result.str().substr(0,2);
|
||||
}
|
||||
|
||||
std::string EncodeSIN::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
result << std::setw(4) << std::hex << std::setfill('0') << src;
|
||||
|
||||
return result.str().substr(2,2) + result.str().substr(0,2);
|
||||
}
|
||||
|
||||
std::string EncodeULG::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
unsigned long src = static_cast<unsigned long>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
result << std::setw(8) << std::hex << std::setfill('0') << src;
|
||||
|
||||
return result.str().substr(6,2) + result.str().substr(4,2) +
|
||||
result.str().substr(2,2) + result.str().substr(0,2);
|
||||
}
|
||||
|
||||
std::string EncodeSLG::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
int src = static_cast<int>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
result << std::setw(8) << std::hex << std::setfill('0') << src;
|
||||
|
||||
return result.str().substr(6,2) + result.str().substr(4,2) +
|
||||
result.str().substr(2,2) + result.str().substr(0,2);
|
||||
}
|
||||
|
||||
std::string EncodeFLT::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short src = static_cast<short>(strtod(m_data.c_str(), NULL) * 1000.0 / m_factor);
|
||||
result << std::setw(4) << std::hex << std::setfill('0') << src;
|
||||
|
||||
return result.str().substr(2,2) + result.str().substr(0,2);
|
||||
}
|
||||
|
||||
std::string EncodeSTR::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
|
||||
for (size_t i = 0; i < m_data.length(); i++)
|
||||
result << std::setw(2) << std::hex << std::setfill('0') << static_cast<short>(m_data[i]);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeBCD::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
|
||||
if (src > 99)
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0xFF);
|
||||
else
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>( ((src / 10) << 4) | (src % 10) );
|
||||
|
||||
return result.str().substr(result.str().length()-2,2);
|
||||
}
|
||||
|
||||
std::string EncodeD1B::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
|
||||
if (src < -127 || src > 127)
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0x80);
|
||||
else
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(src);
|
||||
|
||||
return result.str().substr(result.str().length()-2,2);
|
||||
}
|
||||
|
||||
std::string EncodeD1C::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
float src = static_cast<float>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
|
||||
if (src < 0.0 || src > 100.0)
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0xFF);
|
||||
else
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(src * 2.0);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeD2B::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
float src = static_cast<float>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
|
||||
if (src < -127.999 || src > 127.999) {
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0x80)
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0x00);
|
||||
} else {
|
||||
unsigned char tgt_lsb = static_cast<unsigned>((src - ((short) src)) * 256.0);
|
||||
unsigned char tgt_msb;
|
||||
|
||||
if (src < 0.0 && tgt_lsb != 0x00)
|
||||
tgt_msb = static_cast<unsigned>((short) src - 1);
|
||||
else
|
||||
tgt_msb = static_cast<unsigned>((short) src);
|
||||
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(tgt_msb)
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(tgt_lsb);
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeD2C::encode()
|
||||
{
|
||||
std::ostringstream result;
|
||||
float src = static_cast<float>(strtod(m_data.c_str(), NULL) / m_factor);
|
||||
|
||||
if (src < -2047.999 || src > 2047.999) {
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0x80)
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(0x00);
|
||||
} else {
|
||||
unsigned char tgt_lsb = static_cast<unsigned>(
|
||||
((unsigned char) ( ((short) src) % 16) << 4) +
|
||||
((unsigned char) ( (src - ((short) src)) * 16.0)) );
|
||||
|
||||
unsigned char tgt_msb;
|
||||
|
||||
if (src < 0.0 && tgt_lsb != 0x00)
|
||||
tgt_msb = static_cast<unsigned>((short) (src / 16.0) - 1);
|
||||
else
|
||||
tgt_msb = static_cast<unsigned>((short) src / 16.0);
|
||||
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(tgt_msb)
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<unsigned>(tgt_lsb);
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeBDA::encode()
|
||||
{
|
||||
// prepare data
|
||||
std::string token;
|
||||
std::istringstream stream(m_data);
|
||||
std::vector<std::string> data;
|
||||
|
||||
while (std::getline(stream, token, '.') != 0)
|
||||
data.push_back(token);
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::dec << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[0].c_str(), NULL))
|
||||
<< std::setw(2) << std::dec << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[1].c_str(), NULL))
|
||||
<< std::setw(2) << std::dec << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[2].c_str(), NULL) - 2000);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeHDA::encode()
|
||||
{
|
||||
// prepare data
|
||||
std::string token;
|
||||
std::istringstream stream(m_data);
|
||||
std::vector<std::string> data;
|
||||
|
||||
while (std::getline(stream, token, '.') != 0)
|
||||
data.push_back(token);
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[0].c_str(), NULL))
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[1].c_str(), NULL))
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[2].c_str(), NULL) - 2000);
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeBTI::encode()
|
||||
{
|
||||
// prepare data
|
||||
std::string token;
|
||||
std::istringstream stream(m_data);
|
||||
std::vector<std::string> data;
|
||||
|
||||
while (std::getline(stream, token, ':') != 0)
|
||||
data.push_back(token);
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::dec << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[0].c_str(), NULL))
|
||||
<< std::setw(2) << std::dec << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[1].c_str(), NULL))
|
||||
<< std::setw(2) << std::dec << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[2].c_str(), NULL));
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeHTI::encode()
|
||||
{
|
||||
// prepare data
|
||||
std::string token;
|
||||
std::istringstream stream(m_data);
|
||||
std::vector<std::string> data;
|
||||
|
||||
while (std::getline(stream, token, ':') != 0)
|
||||
data.push_back(token);
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[0].c_str(), NULL))
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[1].c_str(), NULL))
|
||||
<< std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>(strtod(data[2].c_str(), NULL));
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeBDY::encode()
|
||||
{
|
||||
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
|
||||
short day = 7;
|
||||
|
||||
for (short i = 0; i < 7; i++)
|
||||
if (strcasecmp(days[i], m_data.c_str()) == 0)
|
||||
day = i;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::hex << std::setfill('0') << day;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeHDY::encode()
|
||||
{
|
||||
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
|
||||
short day = 8;
|
||||
|
||||
for (short i = 0; i < 7; i++)
|
||||
if (strcasecmp(days[i], m_data.c_str()) == 0)
|
||||
day = i + 1;
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::hex << std::setfill('0') << day;
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string EncodeTTM::encode()
|
||||
{
|
||||
// prepare data
|
||||
std::string token;
|
||||
std::istringstream stream(m_data);
|
||||
std::vector<std::string> data;
|
||||
|
||||
while (std::getline(stream, token, ':') != 0)
|
||||
data.push_back(token);
|
||||
|
||||
std::ostringstream result;
|
||||
result << std::setw(2) << std::hex << std::setfill('0')
|
||||
<< static_cast<short>( (strtod(data[0].c_str(), NULL) * 6)
|
||||
+ (strtod(data[1].c_str(), NULL) / 10) );
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
* crc calculations from http://www.mikrocontroller.net/topic/75698
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_ENCODE_H_
|
||||
#define LIBEBUS_ENCODE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
class Encode
|
||||
{
|
||||
|
||||
public:
|
||||
Encode(const std::string& data, const std::string& factor = "");
|
||||
virtual ~Encode() {}
|
||||
|
||||
virtual std::string encode() = 0;
|
||||
|
||||
protected:
|
||||
std::string m_data;
|
||||
float m_factor;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class EncodeHEX : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeHEX(const std::string& data) : Encode(data) {}
|
||||
~EncodeHEX() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeUCH : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeUCH(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeUCH() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeSCH : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeSCH(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeSCH() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeUIN : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeUIN(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeUIN() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeSIN : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeSIN(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeSIN() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeULG : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeULG(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeULG() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeSLG : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeSLG(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeSLG() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeFLT : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeFLT(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeFLT() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeSTR : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeSTR(const std::string& data) : Encode(data) {}
|
||||
~EncodeSTR() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeBCD : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeBCD(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeBCD() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeD1B : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeD1B(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeD1B() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeD1C : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeD1C(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeD1C() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeD2B : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeD2B(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeD2B() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeD2C : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeD2C(const std::string& data, const std::string& factor)
|
||||
: Encode(data, factor) {}
|
||||
~EncodeD2C() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeBDA : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeBDA(const std::string& data) : Encode(data) {}
|
||||
~EncodeBDA() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeHDA : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeHDA(const std::string& data) : Encode(data) {}
|
||||
~EncodeHDA() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeBTI : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeBTI(const std::string& data) : Encode(data) {}
|
||||
~EncodeBTI() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeHTI : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeHTI(const std::string& data) : Encode(data) {}
|
||||
~EncodeHTI() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeBDY : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeBDY(const std::string& data) : Encode(data) {}
|
||||
~EncodeBDY() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeHDY : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeHDY(const std::string& data) : Encode(data) {}
|
||||
~EncodeHDY() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
class EncodeTTM : public Encode
|
||||
{
|
||||
|
||||
public:
|
||||
EncodeTTM(const std::string& data) : Encode(data) {}
|
||||
~EncodeTTM() {}
|
||||
|
||||
std::string encode();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_ENCODE_H_
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
bool Device::isOpen()
|
||||
{
|
||||
if (isValid() == false)
|
||||
m_open = false;
|
||||
|
||||
return m_open;
|
||||
}
|
||||
|
||||
bool Device::isValid()
|
||||
{
|
||||
if (m_noDeviceCheck == false) {
|
||||
int port;
|
||||
|
||||
if (ioctl(m_fd, TIOCMGET, &port) == -1) {
|
||||
closeDevice();
|
||||
m_open = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ssize_t Device::sendBytes(const unsigned char* buffer, size_t nbytes)
|
||||
{
|
||||
if (isValid() == false)
|
||||
return -1;
|
||||
|
||||
// write bytes to device
|
||||
return write(m_fd, buffer, nbytes);
|
||||
}
|
||||
|
||||
ssize_t Device::recvBytes(const long timeout, size_t maxCount)
|
||||
{
|
||||
if (isValid() == false)
|
||||
return -1; // TODO RESULT_ERR_DEVICE
|
||||
|
||||
if (timeout > 0) {
|
||||
fd_set readfds;
|
||||
struct timeval tdiff;
|
||||
|
||||
// set select timeout
|
||||
tdiff.tv_sec = 0;
|
||||
tdiff.tv_usec = timeout;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(m_fd, &readfds);
|
||||
|
||||
if (select(m_fd + 1, &readfds, NULL, NULL, &tdiff) != 1)
|
||||
return -2; // TODO RESULT_ERR_TIMEOUT
|
||||
}
|
||||
|
||||
ssize_t bytes_read = sizeof(m_buffer);
|
||||
if (maxCount > sizeof(m_buffer))
|
||||
maxCount = sizeof(m_buffer);
|
||||
|
||||
|
||||
// read bytes from device
|
||||
bytes_read = read(m_fd, m_buffer, maxCount);
|
||||
|
||||
for (int i = 0; i < bytes_read; i++)
|
||||
m_recvBuffer.push(m_buffer[i]);
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
unsigned char Device::getByte()
|
||||
{
|
||||
unsigned char byte;
|
||||
|
||||
if (m_recvBuffer.empty() == false) {
|
||||
byte = m_recvBuffer.front();
|
||||
m_recvBuffer.pop();
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void DeviceSerial::openDevice(const std::string deviceName, const bool noDeviceCheck)
|
||||
{
|
||||
m_noDeviceCheck = noDeviceCheck;
|
||||
|
||||
termios newSettings;
|
||||
|
||||
m_open = false;
|
||||
|
||||
// open file descriptor from serial device
|
||||
m_fd = open(deviceName.c_str(), O_RDWR | O_NOCTTY);
|
||||
|
||||
if (m_fd < 0)
|
||||
return;
|
||||
|
||||
// save current settings of serial device
|
||||
tcgetattr(m_fd, &m_oldSettings);
|
||||
|
||||
memset(&newSettings, '\0', sizeof(newSettings));
|
||||
|
||||
newSettings.c_cflag |= (B2400 | CS8 | CLOCAL | CREAD);
|
||||
newSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||||
newSettings.c_iflag |= IGNPAR;
|
||||
newSettings.c_oflag &= ~OPOST;
|
||||
|
||||
newSettings.c_cc[VMIN] = 1;
|
||||
newSettings.c_cc[VTIME] = 0;
|
||||
|
||||
// empty device buffer
|
||||
tcflush(m_fd, TCIOFLUSH);
|
||||
|
||||
// activate new settings of serial device
|
||||
tcsetattr(m_fd, TCSANOW, &newSettings);
|
||||
|
||||
// set serial device into blocking mode
|
||||
fcntl(m_fd, F_SETFL, fcntl(m_fd, F_GETFL) & ~O_NONBLOCK);
|
||||
|
||||
m_open = true;
|
||||
|
||||
}
|
||||
|
||||
void DeviceSerial::closeDevice()
|
||||
{
|
||||
if (m_open == true) {
|
||||
// empty device buffer
|
||||
tcflush(m_fd, TCIOFLUSH);
|
||||
|
||||
// activate old settings of serial device
|
||||
tcsetattr(m_fd, TCSANOW, &m_oldSettings);
|
||||
|
||||
// close file descriptor from serial device
|
||||
close(m_fd);
|
||||
|
||||
m_fd = -1;
|
||||
m_open = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeviceNetwork::openDevice(const std::string deviceName, const bool noDeviceCheck)
|
||||
{
|
||||
m_noDeviceCheck = noDeviceCheck;
|
||||
|
||||
struct sockaddr_in sock;
|
||||
char* hostport;
|
||||
int ret;
|
||||
|
||||
m_open = false;
|
||||
|
||||
memset((char*) &sock, 0, sizeof(sock));
|
||||
|
||||
hostport = strdup(deviceName.c_str());
|
||||
char* host = strtok(hostport, ":");
|
||||
char* port = strtok(NULL, ":");
|
||||
|
||||
if (inet_addr(host) == INADDR_NONE) {
|
||||
struct hostent* he;
|
||||
|
||||
he = gethostbyname(host);
|
||||
if (he == NULL)
|
||||
return;
|
||||
|
||||
memcpy(&sock.sin_addr, he->h_addr_list[0], he->h_length);
|
||||
} else {
|
||||
ret = inet_aton(host, &sock.sin_addr);
|
||||
if (ret == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
sock.sin_family = AF_INET;
|
||||
sock.sin_port = htons(strtol(port, NULL, 10));
|
||||
|
||||
m_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (m_fd < 0)
|
||||
return;
|
||||
|
||||
ret = connect(m_fd, (struct sockaddr*) &sock, sizeof(sock));
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
free(hostport);
|
||||
m_open = true;
|
||||
}
|
||||
|
||||
void DeviceNetwork::closeDevice()
|
||||
{
|
||||
if (m_open == true) {
|
||||
// close file descriptor from network device
|
||||
close(m_fd);
|
||||
|
||||
m_fd = -1;
|
||||
m_open = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Port::Port(const std::string deviceName, const bool noDeviceCheck)
|
||||
: m_deviceName(deviceName), m_noDeviceCheck(noDeviceCheck)
|
||||
{
|
||||
m_device = NULL;
|
||||
|
||||
if (strchr(deviceName.c_str(), '/') == NULL &&
|
||||
strchr(deviceName.c_str(), ':') != NULL)
|
||||
setType(NETWORK);
|
||||
else
|
||||
setType(SERIAL);
|
||||
}
|
||||
|
||||
void Port::setType(const DeviceType type)
|
||||
{
|
||||
if (m_device != NULL)
|
||||
delete m_device;
|
||||
|
||||
switch (type) {
|
||||
case SERIAL:
|
||||
m_device = new DeviceSerial();
|
||||
break;
|
||||
case NETWORK:
|
||||
m_device = new DeviceNetwork();
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_PORT_H_
|
||||
#define LIBEBUS_PORT_H_
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
enum DeviceType { SERIAL, NETWORK };
|
||||
|
||||
#define MAX_READ_SIZE 100
|
||||
|
||||
class Device
|
||||
{
|
||||
|
||||
public:
|
||||
Device() : m_fd(-1), m_open(false), m_noDeviceCheck(false) {}
|
||||
virtual ~Device() {}
|
||||
|
||||
virtual void openDevice(const std::string deviceName, const bool noDeviceCheck) = 0;
|
||||
virtual void closeDevice() = 0;
|
||||
bool isOpen();
|
||||
|
||||
ssize_t sendBytes(const unsigned char* buffer, size_t nbytes);
|
||||
ssize_t recvBytes(const long timeout, size_t maxCount);
|
||||
|
||||
unsigned char getByte();
|
||||
ssize_t sizeRecvBuffer() const { return m_recvBuffer.size(); }
|
||||
|
||||
protected:
|
||||
int m_fd;
|
||||
bool m_open;
|
||||
bool m_noDeviceCheck;
|
||||
std::queue<unsigned char> m_recvBuffer;
|
||||
unsigned char m_buffer[MAX_READ_SIZE];
|
||||
|
||||
private:
|
||||
bool isValid();
|
||||
|
||||
};
|
||||
|
||||
class DeviceSerial : public Device
|
||||
{
|
||||
|
||||
public:
|
||||
~DeviceSerial() { closeDevice(); }
|
||||
|
||||
void openDevice(const std::string deviceName, const bool noDeviceCheck);
|
||||
void closeDevice();
|
||||
|
||||
private:
|
||||
termios m_oldSettings;
|
||||
|
||||
};
|
||||
|
||||
class DeviceNetwork : public Device
|
||||
{
|
||||
|
||||
public:
|
||||
~DeviceNetwork() { closeDevice(); }
|
||||
|
||||
void openDevice(const std::string deviceName, const bool noDeviceCheck);
|
||||
void closeDevice();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Port
|
||||
{
|
||||
|
||||
public:
|
||||
Port(const std::string deviceName, const bool noDeviceCheck);
|
||||
~Port() { delete m_device; }
|
||||
|
||||
void open() { m_device->openDevice(m_deviceName, m_noDeviceCheck); }
|
||||
void close() { m_device->closeDevice(); }
|
||||
bool isOpen() { return m_device->isOpen(); }
|
||||
|
||||
ssize_t send(const unsigned char* buffer, size_t nbytes)
|
||||
{ return m_device->sendBytes(buffer, nbytes); }
|
||||
ssize_t recv(const long timeout, size_t maxCount=MAX_READ_SIZE) { return m_device->recvBytes(timeout, maxCount); }
|
||||
|
||||
unsigned char byte() { return m_device->getByte(); }
|
||||
ssize_t size() const { return m_device->sizeRecvBuffer(); }
|
||||
|
||||
private:
|
||||
std::string m_deviceName;
|
||||
Device* m_device;
|
||||
bool m_noDeviceCheck;
|
||||
|
||||
void setType(const DeviceType type);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_PORT_H_
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) John Baier 2014 <john@johnm.de>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "result.h"
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
const char* getResultCodeCStr(int resultCode) {
|
||||
switch (resultCode) {
|
||||
case RESULT_ERR_SEND: return "ERR_SEND: send error";
|
||||
case RESULT_ERR_EXTRA_DATA: return "ERR_EXTRA_DATA: received bytes > sent bytes";
|
||||
case RESULT_ERR_NAK: return "ERR_NAK: NAK received";
|
||||
case RESULT_ERR_CRC: return "ERR_CRC: CRC error";
|
||||
case RESULT_ERR_ACK: return "ERR_ACK: ACK error";
|
||||
case RESULT_ERR_TIMEOUT: return "ERR_TIMEOUT: read timeout";
|
||||
case RESULT_ERR_SYN: return "ERR_SYN: SYN received";
|
||||
case RESULT_ERR_BUS_LOST: return "ERR_BUS_LOST: lost bus arbitration";
|
||||
case RESULT_ERR_ESC: return "ERR_ESC: invalid escape sequence received";
|
||||
case RESULT_ERR_INVALID_ARG: return "ERR_INVALID_ARG: invalid argument specified";
|
||||
case RESULT_ERR_DEVICE: return "ERR_DEVICE: generic device error";
|
||||
default: return "success";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) John Baier 2014 <john@johnm.de>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_RESULT_H_
|
||||
#define LIBEBUS_RESULT_H_
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
static const int RESULT_OK = 0;
|
||||
|
||||
static const int RESULT_BUS_ACQUIRED = 1; // bus successfully acquired
|
||||
static const int RESULT_DATA = 2; // some data received
|
||||
static const int RESULT_SYN = 3; // regular SYN after message received
|
||||
static const int RESULT_BUS_LOCKED = 4; // bus is locked for access
|
||||
static const int RESULT_BUS_PRIOR_RETRY = 5; // retry to access bus
|
||||
|
||||
static const int RESULT_ERR_SEND = -1; // send error
|
||||
static const int RESULT_ERR_EXTRA_DATA = -2; // received bytes > sent bytes
|
||||
static const int RESULT_ERR_NAK = -3; // NAK received
|
||||
static const int RESULT_ERR_CRC = -4; // CRC error
|
||||
static const int RESULT_ERR_ACK = -5; // ACK error
|
||||
static const int RESULT_ERR_TIMEOUT = -6; // read timeout
|
||||
static const int RESULT_ERR_SYN = -7; // SYN received
|
||||
static const int RESULT_ERR_BUS_LOST = -8; // arbitration lost
|
||||
static const int RESULT_ERR_ESC = -9; // invalid escape sequence received
|
||||
static const int RESULT_ERR_INVALID_ARG = -10; // invalid argument
|
||||
static const int RESULT_ERR_DEVICE = -11; // generic device error (usually fatal)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the string corresponding to the result code.
|
||||
* @param resultCode the result code (see RESULT_ constants).
|
||||
* @return the string corresponding to the result code.
|
||||
*/
|
||||
const char* getResultCodeCStr(int resultCode);
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_RESULT_H_
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) John Baier 2014 <john@johnm.de>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "symbol.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief CRC8 lookup table for the polynom 0x9b = x^8 + x^7 + x^4 + x^3 + x^1 + 1.
|
||||
*/
|
||||
static const unsigned char CRC_LOOKUP_TABLE[]
|
||||
{
|
||||
0x00, 0x9b, 0xad, 0x36, 0xc1, 0x5a, 0x6c, 0xf7, 0x19, 0x82, 0xb4, 0x2f, 0xd8, 0x43, 0x75, 0xee,
|
||||
0x32, 0xa9, 0x9f, 0x04, 0xf3, 0x68, 0x5e, 0xc5, 0x2b, 0xb0, 0x86, 0x1d, 0xea, 0x71, 0x47, 0xdc,
|
||||
0x64, 0xff, 0xc9, 0x52, 0xa5, 0x3e, 0x08, 0x93, 0x7d, 0xe6, 0xd0, 0x4b, 0xbc, 0x27, 0x11, 0x8a,
|
||||
0x56, 0xcd, 0xfb, 0x60, 0x97, 0x0c, 0x3a, 0xa1, 0x4f, 0xd4, 0xe2, 0x79, 0x8e, 0x15, 0x23, 0xb8,
|
||||
0xc8, 0x53, 0x65, 0xfe, 0x09, 0x92, 0xa4, 0x3f, 0xd1, 0x4a, 0x7c, 0xe7, 0x10, 0x8b, 0xbd, 0x26,
|
||||
0xfa, 0x61, 0x57, 0xcc, 0x3b, 0xa0, 0x96, 0x0d, 0xe3, 0x78, 0x4e, 0xd5, 0x22, 0xb9, 0x8f, 0x14,
|
||||
0xac, 0x37, 0x01, 0x9a, 0x6d, 0xf6, 0xc0, 0x5b, 0xb5, 0x2e, 0x18, 0x83, 0x74, 0xef, 0xd9, 0x42,
|
||||
0x9e, 0x05, 0x33, 0xa8, 0x5f, 0xc4, 0xf2, 0x69, 0x87, 0x1c, 0x2a, 0xb1, 0x46, 0xdd, 0xeb, 0x70,
|
||||
0x0b, 0x90, 0xa6, 0x3d, 0xca, 0x51, 0x67, 0xfc, 0x12, 0x89, 0xbf, 0x24, 0xd3, 0x48, 0x7e, 0xe5,
|
||||
0x39, 0xa2, 0x94, 0x0f, 0xf8, 0x63, 0x55, 0xce, 0x20, 0xbb, 0x8d, 0x16, 0xe1, 0x7a, 0x4c, 0xd7,
|
||||
0x6f, 0xf4, 0xc2, 0x59, 0xae, 0x35, 0x03, 0x98, 0x76, 0xed, 0xdb, 0x40, 0xb7, 0x2c, 0x1a, 0x81,
|
||||
0x5d, 0xc6, 0xf0, 0x6b, 0x9c, 0x07, 0x31, 0xaa, 0x44, 0xdf, 0xe9, 0x72, 0x85, 0x1e, 0x28, 0xb3,
|
||||
0xc3, 0x58, 0x6e, 0xf5, 0x02, 0x99, 0xaf, 0x34, 0xda, 0x41, 0x77, 0xec, 0x1b, 0x80, 0xb6, 0x2d,
|
||||
0xf1, 0x6a, 0x5c, 0xc7, 0x30, 0xab, 0x9d, 0x06, 0xe8, 0x73, 0x45, 0xde, 0x29, 0xb2, 0x84, 0x1f,
|
||||
0xa7, 0x3c, 0x0a, 0x91, 0x66, 0xfd, 0xcb, 0x50, 0xbe, 0x25, 0x13, 0x88, 0x7f, 0xe4, 0xd2, 0x49,
|
||||
0x95, 0x0e, 0x38, 0xa3, 0x54, 0xcf, 0xf9, 0x62, 0x8c, 0x17, 0x21, 0xba, 0x4d, 0xd6, 0xe0, 0x7b,
|
||||
};
|
||||
|
||||
|
||||
SymbolString::SymbolString(const std::string str)
|
||||
: m_crc(0)
|
||||
{
|
||||
// parse + escape
|
||||
for (size_t i = 0; i+1 < str.size(); i += 2) {
|
||||
unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16);
|
||||
push_back_escape((unsigned char)value);
|
||||
}
|
||||
// add CRC + escape
|
||||
push_back_escape(m_crc, false);
|
||||
}
|
||||
|
||||
SymbolString::SymbolString(const std::string str, bool escaped)
|
||||
: m_crc(0)
|
||||
{
|
||||
bool previousEscape = false;
|
||||
|
||||
// parse + optionally unescape
|
||||
for (size_t i = 0; i+1 < str.size(); i += 2) {
|
||||
unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16);
|
||||
if (escaped == true) {
|
||||
push_back_unescape((unsigned char)value, previousEscape, false);
|
||||
}
|
||||
else
|
||||
m_data.push_back((unsigned char)value);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string SymbolString::getDataStr(bool unescape)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
bool previousEscape = false;
|
||||
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
unsigned char value = at(i);
|
||||
if (unescape == true && previousEscape == true) {
|
||||
if (value == 0x00) {
|
||||
sstr << "a9"; // ESC
|
||||
}
|
||||
else if (value == 0x01) {
|
||||
sstr << "aa"; // SYN
|
||||
}
|
||||
else {
|
||||
sstr << "XX"; // invalid escape sequence
|
||||
}
|
||||
previousEscape = false;
|
||||
}
|
||||
else if (unescape == true && value == ESC) {
|
||||
previousEscape = true; // escape sequence not yet finished
|
||||
}
|
||||
else {
|
||||
sstr << std::nouppercase << std::setw(2) << std::hex
|
||||
<< std::setfill('0') << static_cast<unsigned>(value);
|
||||
}
|
||||
}
|
||||
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
void SymbolString::push_back_escape(const unsigned char value, bool updateCRC)
|
||||
{
|
||||
if (value == ESC) {
|
||||
m_data.push_back(ESC);
|
||||
m_data.push_back(0x00);
|
||||
if (updateCRC) {
|
||||
addCRC(ESC);
|
||||
addCRC(0x00);
|
||||
}
|
||||
}
|
||||
else if (value == SYN) {
|
||||
m_data.push_back(ESC);
|
||||
m_data.push_back(0x01);
|
||||
if (updateCRC) {
|
||||
addCRC(ESC);
|
||||
addCRC(0x01);
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_data.push_back(value);
|
||||
if (updateCRC) {
|
||||
addCRC(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char SymbolString::push_back_unescape(const unsigned char value, bool& previousEscape, bool updateCRC)
|
||||
{
|
||||
if (updateCRC) {
|
||||
addCRC(value);
|
||||
}
|
||||
if (previousEscape == true) {
|
||||
if (value == 0x00) {
|
||||
m_data.push_back(ESC);
|
||||
previousEscape = false;
|
||||
return ESC;
|
||||
}
|
||||
if (value == 0x01) {
|
||||
m_data.push_back(SYN);
|
||||
previousEscape = false;
|
||||
return SYN;
|
||||
}
|
||||
return 0; // invalid escape sequence
|
||||
}
|
||||
if (value == ESC) {
|
||||
previousEscape = true;
|
||||
return 1; // escape sequence not yet finished
|
||||
}
|
||||
m_data.push_back(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void SymbolString::addCRC(const unsigned char value) {
|
||||
m_crc = CRC_LOOKUP_TABLE[m_crc]^value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool isMaster(unsigned char addr) {
|
||||
unsigned char addrHi = (addr & 0xF0) >> 4;
|
||||
unsigned char addrLo = (addr & 0x0F);
|
||||
|
||||
return ((addrHi == 0x0) || (addrHi == 0x1) || (addrHi == 0x3) || (addrHi == 0x7) || (addrHi == 0xF))
|
||||
&& ((addrLo == 0x0) || (addrLo == 0x1) || (addrLo == 0x3) || (addrLo == 0x7) || (addrLo == 0xF));
|
||||
}
|
||||
|
||||
} //namespace
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) John Baier 2014 <john@johnm.de>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LIBEBUS_SYMBOL_H_
|
||||
#define LIBEBUS_SYMBOL_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
|
||||
namespace libebus
|
||||
{
|
||||
|
||||
|
||||
static const unsigned char ESC = 0xA9; // escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA
|
||||
static const unsigned char SYN = 0xAA; // synchronization symbol
|
||||
static const unsigned char ACK = 0x00; // positive acknowledge
|
||||
static const unsigned char NAK = 0xFF; // negative acknowledge
|
||||
static const unsigned char BROADCAST = 0xFE; // the broadcast destination address
|
||||
|
||||
|
||||
/**
|
||||
* @brief A string of bus symbols.
|
||||
*/
|
||||
class SymbolString
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new empty SymbolString.
|
||||
*/
|
||||
SymbolString() : m_crc(0) {}
|
||||
/**
|
||||
* @brief Creates a new escaped SymbolString from an unescaped hex string and adds the calculated CRC.
|
||||
* @param str the unescaped hex string.
|
||||
*/
|
||||
SymbolString(const std::string str);
|
||||
/**
|
||||
* @brief Creates a new unescaped SymbolString from a hex string.
|
||||
* @param escaped whether the hex string is escaped and shall be unescaped.
|
||||
* @param str the hex string.
|
||||
*/
|
||||
SymbolString(const std::string str, bool escaped);
|
||||
/**
|
||||
* @brief Returns the symbols as hex string.
|
||||
* @param escaped whether to unescape the symbols.
|
||||
* @return the symbols as hex string.
|
||||
*/
|
||||
const std::string getDataStr(bool unescape=false);
|
||||
/**
|
||||
* @brief Returns the symbol at the specified index.
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the symbol at the specified index.
|
||||
* @throw std::out_of_range if @a index is invalid.
|
||||
*/
|
||||
unsigned char at(const size_t index) { return m_data.at(index); }
|
||||
/**
|
||||
* @brief Returns the symbol at the specified index.
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the symbol at the specified index.
|
||||
*/
|
||||
unsigned char operator[](const size_t index) { return m_data[index]; }
|
||||
/**
|
||||
* @brief Returns the symbol at the specified index.
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the symbol at the specified index.
|
||||
*/
|
||||
unsigned char operator[](const size_t index) const { return m_data[index]; }
|
||||
/**
|
||||
* @brief Inserts a the symbol at the specified index.
|
||||
* @param index the index at which to insert the symbol.
|
||||
* @param value the symbol to insert.
|
||||
*/
|
||||
void insert(const size_t index, const unsigned char value) { m_data.insert(m_data.begin()+index, value); }
|
||||
/**
|
||||
* @brief Appends a the symbol to the end of the symbol string and escapes it if necessary.
|
||||
* @param value the symbol to append.
|
||||
* @param updateCrc whether to update the calculated CRC in @a m_crc.
|
||||
*/
|
||||
void push_back_escape(const unsigned char value, bool updateCRC=true);
|
||||
/**
|
||||
* @brief Appends a the symbol to the end of the symbol string and unescapes it.
|
||||
* @param value the symbol to append.
|
||||
* @param previousEscape whether the previous value was the escape symbol (set to false for the initial call).
|
||||
* @param updateCrc whether to update the calculated CRC in @a m_crc.
|
||||
* @return if previousEscape is false on return: the unescaped symbol. otherwise: zero if the escape sequence was invalid, one if the escape sequence is not yet finished.
|
||||
*/
|
||||
unsigned char push_back_unescape(const unsigned char value, bool& previousEscape, bool updateCRC=true);
|
||||
/**
|
||||
* @brief Returns the number of symbols in this symbol string.
|
||||
* @return the number of available symbols.
|
||||
*/
|
||||
size_t size() const { return m_data.size(); }
|
||||
/**
|
||||
* @brief Returns the calculated CRC.
|
||||
* @return the calculated CRC.
|
||||
*/
|
||||
unsigned char getCRC() const { return m_crc; }
|
||||
/**
|
||||
* @brief Clears the symbols.
|
||||
*/
|
||||
void clear() { m_crc=0; m_data.clear(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Updates the calculated CRC in @a m_crc by adding a value.
|
||||
* @param value the (escaped) value to add to the calculated CRC in @a m_crc.
|
||||
*/
|
||||
void addCRC(const unsigned char value);
|
||||
|
||||
/**
|
||||
* @brief the string of bus symbols.
|
||||
*/
|
||||
std::vector<unsigned char> m_data;
|
||||
/**
|
||||
* @brief the calculated CRC.
|
||||
*/
|
||||
unsigned char m_crc;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the address is one of the 25 master addresses.
|
||||
* @param addr the address to check.
|
||||
* @return <code>true</code> if the specified address is a master address.
|
||||
*/
|
||||
bool isMaster(unsigned char addr);
|
||||
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // LIBEBUS_SYMBOL_H_
|
||||
@@ -0,0 +1,37 @@
|
||||
AM_CXXFLAGS = -fpic \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-I$(top_srcdir)/src/libebus
|
||||
|
||||
noinst_PROGRAMS = test_port \
|
||||
test_symbol \
|
||||
test_bus \
|
||||
test_commands \
|
||||
test_configfile \
|
||||
test_decode \
|
||||
test_encode
|
||||
|
||||
test_port_SOURCES = test_port.cpp
|
||||
test_port_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
test_symbol_SOURCES = test_symbol.cpp
|
||||
test_symbol_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
test_bus_SOURCES = test_bus.cpp
|
||||
test_bus_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
test_commands_SOURCES = test_commands.cpp
|
||||
test_commands_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
test_configfile_SOURCES = test_configfile.cpp
|
||||
test_configfile_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
test_decode_SOURCES = test_decode.cpp
|
||||
test_decode_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
test_encode_SOURCES = test_encode.cpp
|
||||
test_encode_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
-rm -rf .libs
|
||||
@@ -0,0 +1,4 @@
|
||||
# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment
|
||||
c;broad;date_time_temp;Datum, Uhrzeit und Aussentempertur;BR;FE;0700;9;-;4;temp;md;1,2;d2b;1.0;°C;-;Temperatur;day;md;8;bdy;-;-;-;Wochentag;date;md;6,7,9;bda;-;-;-;Datum;time;md;5,4,3;bti;-;-;-;Uhrzeit
|
||||
g;ci;Password;Kennwort;MS;15;B509;3;0D2C00;4;pin1;sd;1;uch;-;-;-;Pin 1;pin2;sd;2;uch;-;-;-;Pin 2;pin3;sd;3;uch;-;-;-;Pin 3;pin4;sd;4;uch;-;-;-;Pin 4
|
||||
s;vwxmk;DesiredTemp;Solltemperatur;MS;50;B509;4;0E3200;1;-;sd;1;d1c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "bus.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
int main ()
|
||||
{
|
||||
Bus bus("/dev/ttyUSB0", true, 15000, "/tmp/dump_bus.bin", 100, false);
|
||||
|
||||
bus.connect();
|
||||
|
||||
if (bus.isConnected() == true)
|
||||
std::cout << "connect successful." << std::endl;
|
||||
|
||||
int cout = 0;
|
||||
|
||||
while (cout++ < 1000) {
|
||||
if (bus.isConnected() == true) {
|
||||
bus.printBytes();
|
||||
} else {
|
||||
sleep(5);
|
||||
bus.connect();
|
||||
|
||||
if (bus.isConnected() == false)
|
||||
std::cout << "can't open /dev/ttyUSB0" << std::endl;
|
||||
else
|
||||
std::cout << "reconnect successful." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bus.disconnect();
|
||||
|
||||
if (bus.isConnected() == false)
|
||||
std::cout << "disconnect successful." << std::endl;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "configfile.h"
|
||||
#include "commands.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
// will be part of cfg csv class
|
||||
void readCSV(std::istream& is, Commands& commands){
|
||||
std::string line;
|
||||
|
||||
// read lines
|
||||
while (std::getline(is, line) != 0) {
|
||||
std::vector<std::string> row;
|
||||
std::string column;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
|
||||
std::istringstream stream(line);
|
||||
|
||||
// walk through columns
|
||||
while (std::getline(stream, column, ';') != 0) {
|
||||
row.push_back(column);
|
||||
count++;
|
||||
}
|
||||
|
||||
commands.addCommand(row);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Commands* commands = ConfigCommands("test", CSV).getCommands();
|
||||
std::cout << "Commands: " << commands->sizeCmdDB() << std::endl;
|
||||
|
||||
//~ std::string data("g ci password pin1");
|
||||
std::string data("s vwxmk DesiredTemp");
|
||||
|
||||
int index = commands->findCommand(data);
|
||||
std::cout << "found at index: " << index << std::endl;
|
||||
|
||||
// prepare data
|
||||
std::string token;
|
||||
std::istringstream stream(data);
|
||||
std::vector<std::string> cmd;
|
||||
|
||||
// split stream
|
||||
while (std::getline(stream, token, ' ') != 0)
|
||||
cmd.push_back(token);
|
||||
|
||||
//~ Command* command = new Command(index, (*commands)[index], "ff15b509030d2c0035000401000000cf00");
|
||||
Command* command = new Command(index, (*commands)[index], "19.0");
|
||||
|
||||
//~ std::string result = command->calcResult(cmd);
|
||||
std::string result = command->calcData();
|
||||
std::cout << "result: " << result << std::endl;
|
||||
|
||||
delete command;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "configfile.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
std::string dir("test");
|
||||
ConfigCommands config(dir, CSV);
|
||||
|
||||
Commands* commands = config.getCommands();
|
||||
|
||||
std::cout << "size: " << commands->sizeCmdDB() << std::endl;
|
||||
|
||||
commands->findCommand("g ci Password");
|
||||
|
||||
std::cout << (*commands)[0][0] << std::endl;
|
||||
|
||||
delete commands;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "decode.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Decode* help_dec = NULL;
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// HEX
|
||||
{
|
||||
const char* hex[] = {"53706569636865722020"};
|
||||
for (size_t i = 0; i < sizeof(hex)/sizeof(hex[0]); i++) {
|
||||
help_dec = new DecodeHEX(hex[i]);
|
||||
std::cout << "DecodeHEX: " << std::setw(20) << hex[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// UCH
|
||||
{
|
||||
const char* uch[] = {"00", "01", "7f", "80", "fe", "ff", "a1"};
|
||||
for (size_t i = 0; i < sizeof(uch)/sizeof(uch[0]); i++) {
|
||||
help_dec = new DecodeUCH(uch[i], "1.0");
|
||||
std::cout << "DecodeUCH: " << std::setw(20) << uch[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// SCH
|
||||
{
|
||||
const char* sch[] = {"00", "01", "7f", "80", "fe", "ff", "a1"};
|
||||
for (size_t i = 0; i < sizeof(sch)/sizeof(sch[0]); i++) {
|
||||
help_dec = new DecodeSCH(sch[i], "1.0");
|
||||
std::cout << "DecodeSCH: " << std::setw(20) << sch[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// UIN
|
||||
{
|
||||
const char* uin[] = {"0000", "0001", "7fff", "8000", "fffe", "ffff", "a1b2"};
|
||||
for (size_t i = 0; i < sizeof(uin)/sizeof(uin[0]); i++) {
|
||||
help_dec = new DecodeUIN(uin[i], "1.0");
|
||||
std::cout << "DecodeUIN: " << std::setw(20) << uin[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// SIN
|
||||
{
|
||||
const char* sin[] = {"0000", "0001", "7fff", "8000", "fffe", "ffff", "a1b2"};
|
||||
for (size_t i = 0; i < sizeof(sin)/sizeof(sin[0]); i++) {
|
||||
help_dec = new DecodeSIN(sin[i], "1.0");
|
||||
std::cout << "DecodeSIN: " << std::setw(20) << sin[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// ULG
|
||||
{
|
||||
const char* ulg[] = {"00000000", "00000001", "7fffffff", "80000000", "fffffffe", "ffffffff", "a1b2c3d4"};
|
||||
for (size_t i = 0; i < sizeof(ulg)/sizeof(ulg[0]); i++) {
|
||||
help_dec = new DecodeULG(ulg[i], "1.0");
|
||||
std::cout << "DecodeULG: " << std::setw(20) << ulg[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// SLG
|
||||
{
|
||||
const char* slg[] = {"00000000", "00000001", "7fffffff", "80000000", "fffffffe", "ffffffff", "a1b2c3d4"};
|
||||
for (size_t i = 0; i < sizeof(slg)/sizeof(slg[0]); i++) {
|
||||
help_dec = new DecodeSLG(slg[i], "1.0");
|
||||
std::cout << "DecodeSLG: " << std::setw(20) << slg[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// FLT
|
||||
{
|
||||
const char* flt[] = {"0000", "081b", "2532", "2689", "0851"};
|
||||
for (size_t i = 0; i < sizeof(flt)/sizeof(flt[0]); i++) {
|
||||
help_dec = new DecodeFLT(flt[i], "1.0");
|
||||
std::cout << "DecodeFLT: " << std::setw(20) << flt[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// STR
|
||||
{
|
||||
const char* str[] = {"53706569636865722020", "5644363030" };
|
||||
for (size_t i = 0; i < sizeof(str)/sizeof(str[0]); i++) {
|
||||
help_dec = new DecodeSTR(str[i]);
|
||||
std::cout << "DecodeSTR: " << std::setw(20) << str[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BCD
|
||||
{
|
||||
const char* bcd[] = {"00", "01", "02", "03", "12", "99"};
|
||||
for (size_t i = 0; i < sizeof(bcd)/sizeof(bcd[0]); i++) {
|
||||
help_dec = new DecodeBCD(bcd[i], "1.0");
|
||||
std::cout << "DecodeBCD: " << std::setw(20) << bcd[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D1B
|
||||
{
|
||||
const char* d1b[] = {"00", "01", "7f", "81", "80"};
|
||||
for (size_t i = 0; i < sizeof(d1b)/sizeof(d1b[0]); i++) {
|
||||
help_dec = new DecodeD1B(d1b[i], "1.0");
|
||||
std::cout << "DecodeD1B: " << std::setw(20) << d1b[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D1C
|
||||
{
|
||||
const char* d1c[] = {"00", "64", "c8"};
|
||||
for (size_t i = 0; i < sizeof(d1c)/sizeof(d1c[0]); i++) {
|
||||
help_dec = new DecodeD1C(d1c[i], "1.0");
|
||||
std::cout << "DecodeD1C: " << std::setw(20) << d1c[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D2B
|
||||
{
|
||||
const char* d2b[] = {"0000", "0100", "ffff", "00ff", "0080", "0180", "ff7f"};
|
||||
for (size_t i = 0; i < sizeof(d2b)/sizeof(d2b[0]); i++) {
|
||||
help_dec = new DecodeD2B(d2b[i], "1.0");
|
||||
std::cout << "DecodeD2B: " << std::setw(20) << d2b[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D2C
|
||||
{
|
||||
const char* d2c[] = {"0000", "0100", "ffff", "f0ff", "0080", "0180", "ff7f"};
|
||||
for (size_t i = 0; i < sizeof(d2c)/sizeof(d2c[0]); i++) {
|
||||
help_dec = new DecodeD2C(d2c[i], "1.0");
|
||||
std::cout << "DecodeD2C: " << std::setw(20) << d2c[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BDA
|
||||
{
|
||||
const char* bda[] = {"171113", "220901"};
|
||||
for (size_t i = 0; i < sizeof(bda)/sizeof(bda[0]); i++) {
|
||||
help_dec = new DecodeBDA(bda[i]);
|
||||
std::cout << "DecodeBDA: " << std::setw(20) << bda[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// HDA
|
||||
{
|
||||
const char* hda[] = {"010101", "1f0c1b"};
|
||||
for (size_t i = 0; i < sizeof(hda)/sizeof(hda[0]); i++) {
|
||||
help_dec = new DecodeHDA(hda[i]);
|
||||
std::cout << "DecodeHDA: " << std::setw(20) << hda[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BTI
|
||||
{
|
||||
const char* bti[] = {"010101", "174209", "235959"};
|
||||
for (size_t i = 0; i < sizeof(bti)/sizeof(bti[0]); i++) {
|
||||
help_dec = new DecodeBTI(bti[i]);
|
||||
std::cout << "DecodeBTI: " << std::setw(20) << bti[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// HTI
|
||||
{
|
||||
const char* hti[] = {"010101", "112a09", "173b3b"};
|
||||
for (size_t i = 0; i < sizeof(hti)/sizeof(hti[0]); i++) {
|
||||
help_dec = new DecodeHTI(hti[i]);
|
||||
std::cout << "DecodeHTI: " << std::setw(20) << hti[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BDY
|
||||
{
|
||||
const char* bdy[] = {"01", "03", "06", "07"};
|
||||
for (size_t i = 0; i < sizeof(bdy)/sizeof(bdy[0]); i++) {
|
||||
help_dec = new DecodeBDY(bdy[i]);
|
||||
std::cout << "DecodeBDY: " << std::setw(20) << bdy[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// HDY
|
||||
{
|
||||
const char* hdy[] = {"01", "03", "07", "08"};
|
||||
for (size_t i = 0; i < sizeof(hdy)/sizeof(hdy[0]); i++) {
|
||||
help_dec = new DecodeHDY(hdy[i]);
|
||||
std::cout << "DecodeHDY: " << std::setw(20) << hdy[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// TTM
|
||||
{
|
||||
const char* ttm[] = {"00", "23", "4f", "90"};
|
||||
for (size_t i = 0; i < sizeof(ttm)/sizeof(ttm[0]); i++) {
|
||||
help_dec = new DecodeTTM(ttm[i]);
|
||||
std::cout << "DecodeTTM: " << std::setw(20) << ttm[i] << " = " << help_dec->decode() << std::endl;
|
||||
|
||||
delete help_dec;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "encode.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Encode* help_enc = NULL;
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
// HEX
|
||||
{
|
||||
const char* hex[] = {"53 70 65 69 63 68 65 72 20 20"};
|
||||
for (size_t i = 0; i < sizeof(hex)/sizeof(hex[0]); i++) {
|
||||
help_enc = new EncodeHEX(hex[i]);
|
||||
std::cout << "EncodeHEX: " << std::setw(20) << hex[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// UCH
|
||||
{
|
||||
const char* uch[] = {"0", "1", "127", "128", "254", "255", "161"};
|
||||
for (size_t i = 0; i < sizeof(uch)/sizeof(uch[0]); i++) {
|
||||
help_enc = new EncodeUCH(uch[i], "1.0");
|
||||
std::cout << "EncodeUCH: " << std::setw(20) << uch[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// SCH
|
||||
{
|
||||
const char* sch[] = {"0", "1", "127", "-128", "-2", "-1", "-95"};
|
||||
for (size_t i = 0; i < sizeof(sch)/sizeof(sch[0]); i++) {
|
||||
help_enc = new EncodeSCH(sch[i], "1.0");
|
||||
std::cout << "EncodeSCH: " << std::setw(20) << sch[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// UIN
|
||||
{
|
||||
const char* uin[] = {"0", "1", "32767", "32768", "65534", "65535", "41394"};
|
||||
for (size_t i = 0; i < sizeof(uin)/sizeof(uin[0]); i++) {
|
||||
help_enc = new EncodeUIN(uin[i], "1.0");
|
||||
std::cout << "EncodeUIN: " << std::setw(20) << uin[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// SIN
|
||||
{
|
||||
const char* sin[] = {"0", "1", "32767", "-32768", "-2", "-1", "-24142"};
|
||||
for (size_t i = 0; i < sizeof(sin)/sizeof(sin[0]); i++) {
|
||||
help_enc = new EncodeSIN(sin[i], "1.0");
|
||||
std::cout << "EncodeSIN: " << std::setw(20) << sin[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// ULG
|
||||
{
|
||||
const char* ulg[] = {"0", "1", "2147483647", "2147483648", "4294967294", "4294967295", "2712847316"};
|
||||
for (size_t i = 0; i < sizeof(ulg)/sizeof(ulg[0]); i++) {
|
||||
help_enc = new EncodeULG(ulg[i], "1.0");
|
||||
std::cout << "EncodeULG: " << std::setw(20) << ulg[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// SLG
|
||||
{
|
||||
const char* slg[] = {"0", "1", "2147483647", "-2147483648", "-2", "-1", "-1582119980"};
|
||||
for (size_t i = 0; i < sizeof(slg)/sizeof(slg[0]); i++) {
|
||||
help_enc = new EncodeSLG(slg[i], "1.0");
|
||||
std::cout << "EncodeSLG: " << std::setw(20) << slg[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// FLT
|
||||
{
|
||||
const char* flt[] = {"0.000", "2.075", "9.522", "9.865", "2.129"};
|
||||
for (size_t i = 0; i < sizeof(flt)/sizeof(flt[0]); i++) {
|
||||
help_enc = new EncodeFLT(flt[i], "1.0");
|
||||
std::cout << "EncodeFLT: " << std::setw(20) << flt[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// STR
|
||||
{
|
||||
const char* str[] = {"Speicher ", "VD600" };
|
||||
for (size_t i = 0; i < sizeof(str)/sizeof(str[0]); i++) {
|
||||
help_enc = new EncodeSTR(str[i]);
|
||||
std::cout << "EncodeSTR: " << std::setw(20) << str[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BCD
|
||||
{
|
||||
const char* bcd[] = {"0", "1", "2", "3", "12", "99"};
|
||||
for (size_t i = 0; i < sizeof(bcd)/sizeof(bcd[0]); i++) {
|
||||
help_enc = new EncodeBCD(bcd[i], "1.0");
|
||||
std::cout << "EncodeBCD: " << std::setw(20) << bcd[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D1B
|
||||
{
|
||||
const char* d1b[] = {"00", "01", "127", "-127", "-128"};
|
||||
for (size_t i = 0; i < sizeof(d1b)/sizeof(d1b[0]); i++) {
|
||||
help_enc = new EncodeD1B(d1b[i], "1.0");
|
||||
std::cout << "EncodeD1B: " << std::setw(20) << d1b[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D1C
|
||||
{
|
||||
const char* d1c[] = {"0", "50", "100"};
|
||||
for (size_t i = 0; i < sizeof(d1c)/sizeof(d1c[0]); i++) {
|
||||
help_enc = new EncodeD1C(d1c[i], "1.0");
|
||||
std::cout << "EncodeD1C: " << std::setw(20) << d1c[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D2B
|
||||
{
|
||||
const char* d2b[] = {"0", "0.00390625", "-0.00390625", "-1", "-128", "-127.99609375", "127.99609375"};
|
||||
for (size_t i = 0; i < sizeof(d2b)/sizeof(d2b[0]); i++) {
|
||||
help_enc = new EncodeD2B(d2b[i], "1.0");
|
||||
std::cout << "EncodeD2B: " << std::setw(20) << d2b[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// D2C
|
||||
{
|
||||
const char* d2c[] = {"0", "0.0625", "-0.0625", "-1", "-2048", "-2047.9375", "2047.9375"};
|
||||
for (size_t i = 0; i < sizeof(d2c)/sizeof(d2c[0]); i++) {
|
||||
help_enc = new EncodeD2C(d2c[i], "1.0");
|
||||
std::cout << "EncodeD2C: " << std::setw(20) << d2c[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BDA
|
||||
{
|
||||
const char* bda[] = {"17.11.2013", "22.09.2001"};
|
||||
for (size_t i = 0; i < sizeof(bda)/sizeof(bda[0]); i++) {
|
||||
help_enc = new EncodeBDA(bda[i]);
|
||||
std::cout << "EncodeBDA: " << std::setw(20) << bda[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// HDA
|
||||
{
|
||||
const char* hda[] = {"01.01.2001", "31.12.2027"};
|
||||
for (size_t i = 0; i < sizeof(hda)/sizeof(hda[0]); i++) {
|
||||
help_enc = new EncodeHDA(hda[i]);
|
||||
std::cout << "EncodeHDA: " << std::setw(20) << hda[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BTI
|
||||
{
|
||||
const char* bti[] = {"01:01:01", "17:42:09", "23:59:59"};
|
||||
for (size_t i = 0; i < sizeof(bti)/sizeof(bti[0]); i++) {
|
||||
help_enc = new EncodeBTI(bti[i]);
|
||||
std::cout << "EncodeBTI: " << std::setw(20) << bti[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// HTI
|
||||
{
|
||||
const char* hti[] = {"01:01:01", "17:42:09", "23:59:59"};
|
||||
for (size_t i = 0; i < sizeof(hti)/sizeof(hti[0]); i++) {
|
||||
help_enc = new EncodeHTI(hti[i]);
|
||||
std::cout << "EncodeHTI: " << std::setw(20) << hti[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// BDY
|
||||
{
|
||||
const char* bdy[] = {"Tue", "Thu", "Sun", "Err"};
|
||||
for (size_t i = 0; i < sizeof(bdy)/sizeof(bdy[0]); i++) {
|
||||
help_enc = new EncodeBDY(bdy[i]);
|
||||
std::cout << "EncodeBDY: " << std::setw(20) << bdy[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// HDY
|
||||
{
|
||||
const char* hdy[] = {"Mon", "Wed", "Sun", "Err"};
|
||||
for (size_t i = 0; i < sizeof(hdy)/sizeof(hdy[0]); i++) {
|
||||
help_enc = new EncodeHDY(hdy[i]);
|
||||
std::cout << "EncodeHDY: " << std::setw(20) << hdy[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// TTM
|
||||
{
|
||||
const char* ttm[] = {"00:00", "05:50", "13:10", "24:00"};
|
||||
for (size_t i = 0; i < sizeof(ttm)/sizeof(ttm[0]); i++) {
|
||||
help_enc = new EncodeTTM(ttm[i]);
|
||||
std::cout << "EncodeTTM: " << std::setw(20) << ttm[i] << " = " << help_enc->encode() << std::endl;
|
||||
|
||||
delete help_enc;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
int main ()
|
||||
{
|
||||
std::string dev("/dev/ttyUSB20");
|
||||
Port port(dev, true);
|
||||
|
||||
port.open();
|
||||
|
||||
if(port.isOpen() == true)
|
||||
std::cout << "openPort successful." << std::endl;
|
||||
|
||||
int count = 0;
|
||||
|
||||
while (1) {
|
||||
ssize_t bytes_read;
|
||||
unsigned char byte = 0;
|
||||
bytes_read = port.recv(0);
|
||||
|
||||
for (int i = 0; i < bytes_read; i++)
|
||||
byte = port.byte();
|
||||
std::cout << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<unsigned>(byte) << std::endl;
|
||||
|
||||
bytes_read = 0;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
port.close();
|
||||
|
||||
if(port.isOpen() == false)
|
||||
std::cout << "closePort successful." << std::endl;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) John Baier 2014 <john@johnm.de>
|
||||
*
|
||||
* This file is part of libebus.
|
||||
*
|
||||
* libebus is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* libebus is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with libebus. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "symbol.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace libebus;
|
||||
|
||||
int main ()
|
||||
{
|
||||
SymbolString sstr("10feb5050427a915aa");
|
||||
|
||||
std::stringstream out;
|
||||
for (size_t i = 0; i<sstr.size(); i++) {
|
||||
out << std::nouppercase << std::setw(2) << std::hex
|
||||
<< std::setfill('0') << static_cast<unsigned>(sstr[i]);
|
||||
}
|
||||
|
||||
std::string gotStr = out.str(), expectStr = "10feb5050427a90015a90177";
|
||||
|
||||
if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0)
|
||||
std::cout << "ctor escaped successful." << std::endl;
|
||||
else
|
||||
std::cout << "ctor escaped invalid: got " << gotStr
|
||||
<< ", expected " << expectStr << std::endl;
|
||||
|
||||
unsigned char gotCrc = sstr.getCRC(), expectCrc = 0x77;
|
||||
|
||||
if (gotCrc == expectCrc)
|
||||
std::cout << "CRC successful." << std::endl;
|
||||
else
|
||||
std::cout << "CRC invalid: got 0x"
|
||||
<< std::nouppercase << std::setw(2) << std::hex
|
||||
<< std::setfill('0') << static_cast<unsigned>(gotCrc)
|
||||
<< ", expected 0x"
|
||||
<< std::nouppercase << std::setw(2) << std::hex
|
||||
<< std::setfill('0') << static_cast<unsigned>(expectCrc)
|
||||
<< std::endl;
|
||||
|
||||
gotStr = sstr.getDataStr(true), expectStr = "10feb5050427a915aa77";
|
||||
|
||||
if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0)
|
||||
std::cout << "unescape successful." << std::endl;
|
||||
else
|
||||
std::cout << "unescape invalid: got " << gotStr
|
||||
<< ", expected " << expectStr << std::endl;
|
||||
|
||||
sstr = SymbolString("10feb5050427a90015a90177", true);
|
||||
gotStr = sstr.getDataStr(false);
|
||||
if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0)
|
||||
std::cout << "ctor unescaped successful." << std::endl;
|
||||
else
|
||||
std::cout << "ctor unescaped invalid: got " << gotStr
|
||||
<< ", expected " << expectStr << std::endl;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
AM_CXXFLAGS = -fpic \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-I$(top_srcdir)/src/libcore \
|
||||
-I$(top_srcdir)/src/libebus
|
||||
|
||||
bin_PROGRAMS = ebusctl
|
||||
|
||||
ebusctl_SOURCES = ebusctl.cpp
|
||||
|
||||
ebusctl_LDADD = $(top_srcdir)/src/libcore/libcore.a \
|
||||
$(top_srcdir)/src/libebus/libebus.a
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
-rm -rf .libs
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "libebus.h"
|
||||
#include "port.h"
|
||||
#include "decode.h"
|
||||
#include "appl.h"
|
||||
#include "tcpsocket.h"
|
||||
#include <iostream>
|
||||
Reference in New Issue
Block a user