Merge branch 'master' into dockerbuildtest

# Conflicts:
#	contrib/docker/Dockerfile.arm32v5
#	contrib/docker/Dockerfile.arm32v7
#	make_debian.sh
This commit is contained in:
John
2021-11-10 20:33:44 +01:00
37 changed files with 871 additions and 959 deletions
+21 -1
View File
@@ -1,12 +1,32 @@
# 21.3 (tbd)
# 21.3 (2021-11-07)
## Bug Fixes
* fix for escaping double quote in CSV format
* adjusted helper shell scripts and Munin plugin to newer netcat
* fix for weekday in BDA data type (for sending only)
* fix some compiler warnings
* fix non-unique message keys in HTTP JSON output with "full" query parameter
* fix for message after debian install
* fix for replacing already existing message definitions
* fix missing length in CSV dump for some data types
* fix some missing data type lengths in "grab decode" result
* fix for injecting several messages via command line args
## Features
* added DTM and BDZ data types
* added "-n" argument to "hex" and "direct" commands for automatically determining message length from input
* added level/pollprio/condition/field flags and field result type as well as list of types to HTTP JSON output
* added message dump from commandline in JSON format
* added support for newer MQTT broker versions
* added some PIC calibration data to "ebuspicloader" verbose output
* added support for upcoming adapter 3 firmware enhancements
* added config override path
* added support for adding message definition, retrieving data types and raw messages, and decode data types from raw values to HTTP port
* added "--mqttverbose" option
* added verbose option to "info" command
## Breaking Changes
* remove support for Debian 8 Jessie in docker
# 21.2 (2021-02-08)
+1 -1
View File
@@ -1 +1 @@
21.2
21.3
+1 -1
View File
@@ -2,7 +2,7 @@
# Contributor: Milan Knizek <knizek volny cz>
# Usage: makepkg
pkgname=ebusd
pkgver=21.2
pkgver=21.3
pkgrel=1
pkgdesc="ebusd, the daemon for communication with eBUS heating systems."
arch=('i686' 'x86_64' 'armv6h' 'armv7h' 'aarch64')
+1 -1
View File
@@ -3,7 +3,7 @@
# Usage: makepkg -p PKGBUILD.git
pkgname=ebusd-git
_gitname=ebusd
pkgver=21.2
pkgver=21.3
pkgrel=1
pkgdesc="ebusd, the daemon for communication with eBUS heating systems."
arch=('i686' 'x86_64' 'armv6h' 'armv7h' 'aarch64')
+20 -10
View File
@@ -1,5 +1,6 @@
ARG BASE_IMAGE
FROM debian:bullseye as build
FROM $BASE_IMAGE as build
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
@@ -9,25 +10,34 @@ RUN apt-get update && apt-get install -y \
WORKDIR /build
ENV EBUSD_ARCH amd64
ENV EBUSD_VERSION 21.2
ARG TARGETARCH
ARG TARGETVARIANT
ARG EBUSD_VERSION
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
ADD . /build
RUN ./make_debian.sh
FROM debian:bullseye-slim
FROM $BASE_IMAGE-slim as image
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH amd64
ARG TARGETARCH
ARG TARGETVARIANT
ARG EBUSD_VERSION
ARG EBUSD_IMAGE
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}-devel"
@@ -39,6 +49,6 @@ RUN dpkg -i ebusd.deb \
EXPOSE 8888
COPY docker-entrypoint.sh /
COPY --from=build /build/contrib/docker/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-42
View File
@@ -1,42 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM arm32v5/debian:jessie as build
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
ADD . /build
WORKDIR /build
ENV EBUSD_ARCH arm32v5
ENV EBUSD_VERSION 21.2
RUN ./make_debian.sh --host `gcc -dumpmachine`
FROM arm32v5/debian:jessie-slim
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH arm32v5
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}-devel"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-arm-static
EXPOSE 8888
COPY --from=build /build/contrib/docker/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-42
View File
@@ -1,42 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM arm32v7/debian:jessie as build
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
ADD . /build
WORKDIR /build
ENV EBUSD_ARCH arm32v7
ENV EBUSD_VERSION 21.2
RUN ./make_debian.sh
FROM arm32v7/debian:jessie-slim
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH arm32v7
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}-devel"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-arm-static
EXPOSE 8888
COPY --from=build /build/contrib/docker/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-44
View File
@@ -1,44 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM arm64v8/debian:bullseye as build
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ENV EBUSD_ARCH arm64v8
ENV EBUSD_VERSION 21.2
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
FROM arm64v8/debian:bullseye-slim
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH arm64v8
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}-devel"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-aarch64-static
EXPOSE 8888
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-44
View File
@@ -1,44 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM i386/debian:bullseye as build
COPY --from=qemu /usr/bin/qemu-i386-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ENV EBUSD_ARCH i386
ENV EBUSD_VERSION 21.2
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
FROM i386/debian:bullseye-slim
COPY --from=qemu /usr/bin/qemu-i386-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH i386
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}-devel"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-i386-static
EXPOSE 8888
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
+21 -11
View File
@@ -1,5 +1,6 @@
ARG BASE_IMAGE
FROM debian:bullseye as build
FROM $BASE_IMAGE as build
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
@@ -9,29 +10,38 @@ RUN apt-get update && apt-get install -y \
WORKDIR /build
ENV EBUSD_ARCH amd64
ENV EBUSD_VERSION 21.2
ARG TARGETARCH
ARG TARGETVARIANT
ARG EBUSD_VERSION
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
ADD . /build
RUN ./make_debian.sh
FROM debian:bullseye-slim
FROM $BASE_IMAGE-slim as image
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH amd64
ARG TARGETARCH
ARG TARGETVARIANT
ARG EBUSD_VERSION
ARG EBUSD_IMAGE
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
ADD https://github.com/john30/ebusd/releases/download/v${EBUSD_VERSION}/ebusd-${EBUSD_VERSION}_${TARGETARCH}${TARGETVARIANT}-${EBUSD_IMAGE}_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
@@ -39,6 +49,6 @@ RUN dpkg -i ebusd.deb \
EXPOSE 8888
COPY docker-entrypoint.sh /
COPY contrib/docker/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-44
View File
@@ -1,44 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM arm32v5/debian:bullseye as build
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ENV EBUSD_ARCH arm32v5
ENV EBUSD_VERSION 21.2
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
FROM arm32v5/debian:bullseye-slim
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH arm32v5
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-arm-static
EXPOSE 8888
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-44
View File
@@ -1,44 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM arm32v7/debian:bullseye as build
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ENV EBUSD_ARCH arm32v7
ENV EBUSD_VERSION 21.2
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
FROM arm32v7/debian:bullseye-slim
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH arm32v7
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-arm-static
EXPOSE 8888
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-44
View File
@@ -1,44 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM arm64v8/debian:bullseye as build
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ENV EBUSD_ARCH arm64v8
ENV EBUSD_VERSION 21.2
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
FROM arm64v8/debian:bullseye-slim
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH arm64v8
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-aarch64-static
EXPOSE 8888
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
-44
View File
@@ -1,44 +0,0 @@
FROM multiarch/qemu-user-static as qemu
FROM i386/debian:bullseye as build
COPY --from=qemu /usr/bin/qemu-i386-static /usr/bin/
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
autoconf automake g++ make git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
ENV EBUSD_ARCH i386
ENV EBUSD_VERSION 21.2
RUN git clone https://github.com/john30/ebusd.git /build \
&& ./make_debian.sh
FROM i386/debian:bullseye-slim
COPY --from=qemu /usr/bin/qemu-i386-static /usr/bin/
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2
ENV EBUSD_ARCH i386
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb /usr/bin/qemu-i386-static
EXPOSE 8888
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
+25 -15
View File
@@ -1,6 +1,7 @@
%QEMU_FROM_LINE%
FROM %BASE_IMAGE% as build
%QEMU_FROM_COPY%
ARG BASE_IMAGE
FROM $BASE_IMAGE as build
RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \
@@ -9,36 +10,45 @@ RUN apt-get update && apt-get install -y \
WORKDIR /build
ENV EBUSD_ARCH %EBUSD_ARCH%
ENV EBUSD_VERSION %EBUSD_VERSION%
ARG TARGETARCH
ARG TARGETVARIANT
ARG EBUSD_VERSION
RUN git clone https://github.com/john30/ebusd.git /build \
&& %EBUSD_MAKE%
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
ADD . /build
RUN %EBUSD_MAKE%
%EBUSD_UPLOAD_LINES%
FROM %BASE_IMAGE%-slim
%QEMU_FROM_COPY%
FROM $BASE_IMAGE-slim as image
RUN apt-get update && apt-get install -y \
logrotate libmosquitto1 libstdc++6 libc6 libgcc1 \
libmosquitto1 libstdc++6 libc6 libgcc1 \
&& rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION %EBUSD_VERSION%
ENV EBUSD_ARCH %EBUSD_ARCH%
ARG TARGETARCH
ARG TARGETVARIANT
ARG EBUSD_VERSION
ARG EBUSD_IMAGE
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}%EBUSD_VERSION_VARIANT%"
COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb
%EBUSD_COPYDEB%
RUN dpkg -i ebusd.deb \
&& ebusd -V \
&& rm -f ebusd.deb%EXTRA_RM%
&& rm -f ebusd.deb
EXPOSE 8888
COPY docker-entrypoint.sh /
%EBUSD_COPYENTRY%
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"]
+6 -7
View File
@@ -2,8 +2,8 @@ ebusd Docker image
==================
An [ebusd](https://github.com/john30/ebusd/) Docker image is available on the
[Docker Hub](https://hub.docker.com/r/john30/ebusd/) and comes with the latest German
[configuration files](https://github.com/john30/ebusd-configuration/).
[Docker Hub](https://hub.docker.com/r/john30/ebusd/) and is able to download the latest released German
[configuration files](https://github.com/john30/ebusd-configuration/) from a dedicated webservice.
It allows you to run ebusd without actually installing (or even building) it on your system.
You might even be able to run it on a non-Linux operating system, which is at least known to
@@ -18,12 +18,11 @@ To download the latest release image from the hub, use the following command:
The image is able to run on any of the following architectures and the right image will be picked automatically:
* amd64
* i386
* arm32v5
* arm32v7
* arm64v8
In addition to the default "latest" tag, a development set of images is available with "devel" tag. This is built
automatically with every commit to the git repository. Run the following command to use it:
Due to changes of docker hub policies, the development set of images with "devel" tag are currently not automatically
built with every commit to the git repository. Run the following command to use it:
> docker pull john30/ebusd:devel
@@ -54,9 +53,9 @@ Using a network device
When using a network device, the "--device" argument to docker can be omitted, but the device information has to be
passed on to ebusd:
> docker run --rm -it -p 8888 john30/ebusd -f --scanconfig -d udp:192.168.178.123:10000 --latency=80
> docker run --rm -it -p 8888 john30/ebusd -f --scanconfig -d 192.168.178.123:10000 --latency=20
Note: the "-f" and "--scanconfig" arguments are only passed to ebusd if it is called without any additional arguments.
Note: the default "-f" and "--scanconfig" arguments are only passed to ebusd if it is called without any additional arguments.
So when passing further arguments, these two usually need to be added as well.
+52 -17
View File
@@ -1,20 +1,55 @@
#!/bin/bash
archs='amd64 i386 arm32v5 arm32v7 arm64v8'
images='stretch buster bullseye'
UPLOAD_URL='http://'`hostname`'/ebusdreleaseupload.php'
if [[ -z "$1" ]]; then
echo "usage: $0 [release|UPLOADHOST]"
echo " without arguments: build and push devel docker images"
echo " release: build and push release docker images from latest release binaries"
echo " UPLOADHOST: build Debian release packages (with and without MQTT) and upload them to UPLOADHOST"
exit 1
fi
archs=linux/amd64,linux/386,linux/arm/v7,linux/arm64
if [[ -z "$1" ]] || [[ "x$1" == "xrelease" ]]; then
UPLOAD_URL=
else
UPLOAD_URL="http://$1/ebusdreleaseupload.php"
fi
UPLOAD_CREDENTIALS='anonymous:build'
for image in $images; do
dir=$image
mkdir -p $dir
BASE_IMAGE=debian:$image ./update.sh $dir/
for arch in $archs; do
if [ "$arch" != "amd64" ]; then
suffix=".$arch"
else
suffix=''
fi
docker build $@ --target build --build-arg "UPLOAD_URL=$UPLOAD_URL" --build-arg "UPLOAD_CREDENTIALS=$UPLOAD_CREDENTIALS" --build-arg "UPLOAD_OS=$image" -f $dir/Dockerfile$suffix .
done
rm -rf $dir
done
version=`cat ../../VERSION`
source='../..'
images='bullseye'
if [[ -z "$1" ]]; then
namesuffix=''
target=image
outputFmt='-o type=docker,type=registry'
tagsuffix=':devel'
elif [[ "x$1" = "xrelease" ]]; then
archs=linux/amd64
namesuffix='.release'
target=image
outputFmt='-o type=docker,type=registry'
tagsuffix=":v$version"
else
namesuffix='.build'
target=build
images='bullseye buster stretch'
outputFmt=-q
tagsuffix=":v$version-prep"
fi
for image in $images; do
output=$(echo "$outputFmt"|sed -e "s#%IMAGE%#$image#g")
docker buildx build \
--target $target \
--progress pain \
--platform $archs \
-f Dockerfile${namesuffix} \
--build-arg "BASE_IMAGE=debian:$image" \
--build-arg "EBUSD_VERSION=$version" \
--build-arg "EBUSD_IMAGE=$image" \
--build-arg "UPLOAD_URL=$UPLOAD_URL" \
--build-arg "UPLOAD_CREDENTIALS=$UPLOAD_CREDENTIALS" \
--build-arg "UPLOAD_OS=$image" \
-t ebusd$tagsuffix \
$output \
$source
done
+20 -46
View File
@@ -1,63 +1,37 @@
#!/bin/bash
DEFAULT_IMAGE=debian:bullseye
EBUSD_VERSION=`cat ../../VERSION`
archs='amd64 i386 arm32v5:arm arm32v7:arm arm64v8:aarch64'
function replaceTemplate () {
prefix=
suffix=
qemu_from_line=
qemu_from_copy=
extra_rm=
if [ "$arch" != "amd64" ]; then
qemu="${arch##*:}"
arch="${arch%%:*}"
prefix="$arch/"
suffix=".$arch"
qemu_from_line="FROM multiarch/qemu-user-static as qemu"
qemu_from_copy="COPY --from=qemu /usr/bin/qemu-$qemu-static /usr/bin/"
extra_rm=" /usr/bin/qemu-$qemu-static"
fi
file="${dir}Dockerfile${namesuffix}${suffix}"
file="Dockerfile${namesuffix}"
sed \
-e "s#%QEMU_FROM_LINE%#${qemu_from_line}#g" \
-e "s#%BASE_IMAGE%#${prefix}${BASE_IMAGE:-$DEFAULT_IMAGE}#g" \
-e "s#%QEMU_FROM_COPY%#${qemu_from_copy}#g" \
-e "s#%EBUSD_MAKE%#${make}#g" \
-e "s#%EBUSD_VERSION%#${EBUSD_VERSION}#g" \
-e "s#%EBUSD_VERSION_VARIANT%#${version_variant}#g" \
-e "s#%EBUSD_ARCH%#${arch}#g" \
-e "s#%EXTRA_RM%#${extra_rm}#g" \
-e "s#%EBUSD_UPLOAD_LINES%#${upload_lines}#g" \
-e "s#%EBUSD_COPYDEB%#${copydeb}#g" \
-e "s#%EBUSD_COPYENTRY%#${copyentry}#g" \
Dockerfile.template > "$file"
echo "updated $file"
}
if [[ -z "$1" ]]; then
# devel updates
version_variant='-devel'
make='./make_debian.sh'
dir=''
upload_line=''
namesuffix=''
for arch in $archs; do
replaceTemplate
done
fi
# devel update
version_variant='-devel'
make='./make_debian.sh'
upload_lines=''
copydeb='COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb'
copyentry='COPY --from=build /build/contrib/docker/docker-entrypoint.sh /'
namesuffix=''
replaceTemplate
# release updates
# release update
version_variant=''
dir="$1"
copydeb="ADD https://github.com/john30/ebusd/releases/download/v\${EBUSD_VERSION}/ebusd-\${EBUSD_VERSION}_\${TARGETARCH}\${TARGETVARIANT}-\${EBUSD_IMAGE}_mqtt1.deb ebusd.deb"
copyentry='COPY contrib/docker/docker-entrypoint.sh /'
namesuffix='.release'
replaceTemplate
if [[ -n "$1" ]]; then
# build releases update
make='./make_all.sh'
upload_lines='ARG UPLOAD_URL\nARG UPLOAD_CREDENTIALS\nARG UPLOAD_OS\nRUN if [ -n "\$UPLOAD_URL" ] \&\& [ -n "\$UPLOAD_CREDENTIALS" ]; then for img in ebusd-*.deb; do echo -n "upload \$img: "; curl -fs -u "\$UPLOAD_CREDENTIALS" -X POST --data-binary "@\$img" -H "Content-Type: application/octet-stream" "\$UPLOAD_URL/\$img?a=\$EBUSD_ARCH\&o=\$UPLOAD_OS\&v=\$EBUSD_VERSION" || echo "failed"; done; fi'
namesuffix=''
else
make='./make_debian.sh'
namesuffix='.release'
fi
for arch in $archs; do
namesuffix='.build'
replaceTemplate
done
fi
+287 -302
View File
@@ -10,86 +10,19 @@ paths:
get:
summary: Get all messages of all circuits.
parameters:
- name: since
in: query
description: limit to messages that have changed since the specified UTC seconds.
allowEmptyValue: false
schema:
minimum: 0
type: integer
- name: poll
in: query
description: set the poll priority of matching message(s) to prio.
allowEmptyValue: false
schema:
minimum: 0
type: integer
- name: verbose
in: query
description: include comments and field units.
allowEmptyValue: false
schema:
type: boolean
- name: indexed
in: query
description: always return field indexes instead of names.
allowEmptyValue: false
schema:
type: boolean
- name: numeric
in: query
description: return numeric values of value list entries.
allowEmptyValue: false
schema:
type: boolean
- name: valuename
in: query
description: include value and name for named values.
allowEmptyValue: false
schema:
type: boolean
- name: full
in: query
description: include all available attributes.
allowEmptyValue: false
schema:
type: boolean
- name: required
in: query
description: retrieve the data from the bus if not yet cached.
allowEmptyValue: false
schema:
type: boolean
- name: write
in: query
description: retrieve write messages in addition to read/poll messages.
allowEmptyValue: false
schema:
type: boolean
- name: raw
in: query
description: include raw master/slave data.
allowEmptyValue: false
schema:
type: boolean
- name: def
in: query
description: include message and field definition.
allowEmptyValue: false
schema:
type: boolean
- name: user
in: query
description: authenticate with user name.
allowEmptyValue: false
schema:
type: string
- name: secret
in: query
description: authenticate with user secret.
allowEmptyValue: false
schema:
type: string
- $ref: '#/components/parameters/sinceQuery'
- $ref: '#/components/parameters/pollQuery'
- $ref: '#/components/parameters/verboseQuery'
- $ref: '#/components/parameters/indexedQuery'
- $ref: '#/components/parameters/numericQuery'
- $ref: '#/components/parameters/valuenameQuery'
- $ref: '#/components/parameters/fullQuery'
- $ref: '#/components/parameters/requiredQuery'
- $ref: '#/components/parameters/writeQuery'
- $ref: '#/components/parameters/rawQuery'
- $ref: '#/components/parameters/defQuery'
- $ref: '#/components/parameters/userQuery'
- $ref: '#/components/parameters/secretQuery'
responses:
200:
description: Success.
@@ -118,92 +51,20 @@ paths:
required: true
schema:
type: string
- name: since
in: query
description: limit to messages that have changed since the specified UTC seconds.
allowEmptyValue: false
schema:
minimum: 0
type: integer
- name: poll
in: query
description: set the poll priority of matching message(s) to prio.
allowEmptyValue: false
schema:
minimum: 0
type: integer
- name: exact
in: query
description: exact search for circuit/message name.
allowEmptyValue: false
schema:
type: boolean
- name: verbose
in: query
description: include comments and field units.
allowEmptyValue: false
schema:
type: boolean
- name: indexed
in: query
description: always return field indexes instead of names.
allowEmptyValue: false
schema:
type: boolean
- name: numeric
in: query
description: return numeric values of value list entries.
allowEmptyValue: false
schema:
type: boolean
- name: valuename
in: query
description: include value and name for named values.
allowEmptyValue: false
schema:
type: boolean
- name: full
in: query
description: include all available attributes.
allowEmptyValue: false
schema:
type: boolean
- name: required
in: query
description: retrieve the data from the bus if not yet cached.
allowEmptyValue: false
schema:
type: boolean
- name: write
in: query
description: retrieve write messages in addition to read/poll messages.
allowEmptyValue: false
schema:
type: boolean
- name: raw
in: query
description: include raw master/slave data.
allowEmptyValue: false
schema:
type: boolean
- name: def
in: query
description: include message and field definition.
allowEmptyValue: false
schema:
type: boolean
- name: user
in: query
description: authenticate with user name.
allowEmptyValue: false
schema:
type: string
- name: secret
in: query
description: authenticate with user secret.
allowEmptyValue: false
schema:
type: string
- $ref: '#/components/parameters/sinceQuery'
- $ref: '#/components/parameters/pollQuery'
- $ref: '#/components/parameters/exactQuery'
- $ref: '#/components/parameters/verboseQuery'
- $ref: '#/components/parameters/indexedQuery'
- $ref: '#/components/parameters/numericQuery'
- $ref: '#/components/parameters/valuenameQuery'
- $ref: '#/components/parameters/fullQuery'
- $ref: '#/components/parameters/requiredQuery'
- $ref: '#/components/parameters/writeQuery'
- $ref: '#/components/parameters/rawQuery'
- $ref: '#/components/parameters/defQuery'
- $ref: '#/components/parameters/userQuery'
- $ref: '#/components/parameters/secretQuery'
responses:
200:
description: Success.
@@ -237,92 +98,21 @@ paths:
required: true
schema:
type: string
- name: since
in: query
description: limit to messages that have changed since the specified UTC seconds.
allowEmptyValue: false
schema:
minimum: 0
type: integer
- name: poll
in: query
description: set the poll priority of matching message(s) to prio.
allowEmptyValue: false
schema:
minimum: 0
type: integer
- name: exact
in: query
description: exact search for circuit/message name.
allowEmptyValue: false
schema:
type: boolean
- name: verbose
in: query
description: include comments and field units.
allowEmptyValue: false
schema:
type: boolean
- name: indexed
in: query
description: always return field indexes instead of names.
allowEmptyValue: false
schema:
type: boolean
- name: numeric
in: query
description: return numeric values of value list entries.
allowEmptyValue: false
schema:
type: boolean
- name: valuename
in: query
description: include value and name for named values.
allowEmptyValue: false
schema:
type: boolean
- name: full
in: query
description: include all available attributes.
allowEmptyValue: false
schema:
type: boolean
- name: required
in: query
description: retrieve the data from the bus if not yet cached.
allowEmptyValue: false
schema:
type: boolean
- name: write
in: query
description: retrieve write messages in addition to read/poll messages.
allowEmptyValue: false
schema:
type: boolean
- name: raw
in: query
description: include raw master/slave data.
allowEmptyValue: false
schema:
type: boolean
- name: def
in: query
description: include message and field definition.
allowEmptyValue: false
schema:
type: boolean
- name: user
in: query
description: authenticate with user name.
allowEmptyValue: false
schema:
type: string
- name: secret
in: query
description: authenticate with user secret.
allowEmptyValue: false
schema:
type: string
- $ref: '#/components/parameters/sinceQuery'
- $ref: '#/components/parameters/pollQuery'
- $ref: '#/components/parameters/exactQuery'
- $ref: '#/components/parameters/verboseQuery'
- $ref: '#/components/parameters/indexedQuery'
- $ref: '#/components/parameters/numericQuery'
- $ref: '#/components/parameters/valuenameQuery'
- $ref: '#/components/parameters/fullQuery'
- $ref: '#/components/parameters/requiredQuery'
- $ref: '#/components/parameters/writeQuery'
- $ref: '#/components/parameters/rawQuery'
- $ref: '#/components/parameters/defQuery'
- $ref: '#/components/parameters/defineQuery'
- $ref: '#/components/parameters/userQuery'
- $ref: '#/components/parameters/secretQuery'
responses:
200:
description: Success
@@ -333,6 +123,66 @@ paths:
500:
description: Circuit or message not found.
content: { }
/datatypes:
get:
summary: Get all known field data types.
responses:
200:
description: Success.
content:
application/json;charset=utf-8:
schema:
$ref: '#/components/schemas/DataTypes'
400:
description: Invalid request parameters.
content: { }
403:
description: User not authorized.
content: { }
404:
description: Circuit or message not found.
content: { }
500:
description: General error.
content: { }
/raw:
get:
summary: Retrieve raw data from grabbed and/or decoded messages.
parameters:
- $ref: '#/components/parameters/sinceQuery'
responses:
200:
description: Success
content:
application/json;charset=utf-8:
schema:
$ref: '#/components/schemas/RawMessages'
/decode:
get:
summary: Decode raw data with the specified field defintion.
parameters:
- name: def
in: query
description: the field definition (starting with type).
allowEmptyValue: false
required: true
schema:
type: string
- name: raw
in: query
description: the raw symbols to decode as hex sequence.
required: true
allowEmptyValue: false
schema:
type: string
pattern: '^([0-9a-f][0-9a-f])+$'
responses:
200:
description: Success
content:
application/json;charset=utf-8:
schema:
$ref: '#/components/schemas/FieldValue'
/{file}:
get:
summary: Retrieve a particular file.
@@ -391,36 +241,36 @@ paths:
500:
description: General error.
content: { }
head:
summary: Retrieve headers for a certain file.
parameters:
- name: file
in: path
description: the file to retrieve.
required: true
schema:
type: string
responses:
200:
description: Success
content:
application/json;charset=utf-8:
schema:
$ref: '#/components/schemas/Data'
400:
description: Circuit or message not found.
content: { }
# head:
# summary: Retrieve headers for a certain file.
# parameters:
# - name: file
# in: path
# description: the file to retrieve.
# required: true
# schema:
# type: string
# responses:
# 200:
# description: Success
# content:
# application/json;charset=utf-8:
# schema:
# $ref: '#/components/schemas/Data'
# 400:
# description: Circuit or message not found.
# content: { }
components:
schemas:
Global:
required:
- lastup
- version
- signal
- reconnects
- masters
- messages
- reconnects
- signal
- version
- lastup
type: object
properties:
version:
@@ -433,6 +283,12 @@ components:
description: the result of update check ("OK" or string describing available
updates).
example: revision 1234abd available, 5 newer configuration files available
user:
type: string
description: logged in user name.
access:
type: string
description: access level(s) of the logged in user.
signal:
type: boolean
description: whether signal is available.
@@ -447,6 +303,26 @@ components:
type: integer
description: the maximum symbol rate on the bus seen since start.
example: 167
minarbitrationmicros:
minimum: 0
type: integer
description: the minimum arbitration delay in microseconds.
example: 4231
maxarbitrationmicros:
minimum: 0
type: integer
description: the maximum arbitration delay in microseconds.
example: 4892
minsymbollatency:
minimum: 0
type: integer
description: the minimum symbol latency in milliseconds.
example: 4
maxsymbollatency:
minimum: 0
type: integer
description: the maximum symbol latency in milliseconds.
example: 9
qq:
maximum: 255
minimum: 0
@@ -487,14 +363,15 @@ components:
example: 8
messages:
type: object
description: the messages with the unique key per circuit.
additionalProperties:
$ref: '#/components/schemas/Message'
Message:
required:
- lastup
- name
- passive
- write
- lastup
type: object
properties:
name:
@@ -506,6 +383,16 @@ components:
write:
type: boolean
description: true for a write message, false for a read message.
level:
type: string
description: the access level for the message (only with full).
pollprios:
description: the poll priority of the message (only with full).
type: integer
minimum: 0
condition:
type: string
description: the condition string in case of a conditional message (only with full).
lastup:
minimum: 0
type: integer
@@ -515,7 +402,7 @@ components:
maximum: 255
minimum: 0
type: integer
description: limited source master address (only with def).
description: limited source master address (only with def or data).
example: 49
zz:
maximum: 255
@@ -535,30 +422,34 @@ components:
type: string
description: the message comment (only with verbose).
master:
type: array
$ref: '#/components/schemas/Symbols'
description: the last seen master data bytes (only with raw and if available).
items:
maximum: 255
minimum: 0
type: integer
slave:
type: array
$ref: '#/components/schemas/Symbols'
description: the last seen slave data bytes (only with raw and if available).
items:
maximum: 255
minimum: 0
type: integer
fields:
type: object
additionalProperties:
$ref: '#/components/schemas/Field'
description: the decoded fields the message is composed of (only if available).
decodeerror:
type: string
description: set to the error message instead of fields in case of a decoding error.
fielddefs:
type: array
description: the field definitions the message is composed of (only with
def).
items:
$ref: '#/components/schemas/FieldDef'
Symbols:
description: master or slave data bytes.
type: array
minItems: 1
maximum: 32
items:
maximum: 255
minimum: 0
type: integer
Field:
type: object
properties:
@@ -566,7 +457,7 @@ components:
type: string
description: the field name.
value:
type: object
$ref: '#/components/schemas/FieldValue'
description: the field value.
unit:
type: string
@@ -574,13 +465,19 @@ components:
comment:
type: string
description: the field comment (only with verbose).
FieldValue:
description: the field value.
oneOf:
- type: string
- type: number
nullable: true
FieldDef:
required:
- isbits
- length
- name
- slave
- type
- isbits
- length
type: object
properties:
name:
@@ -601,7 +498,8 @@ components:
when isbits is true).
divisor:
type: number
description: the extra divisor applied to the raw value (only if applicable).
description: the divisor for numeric types (only if applicable, positive
for divisor, negative for reciprocal i.e. 1/-divisor).
value:
type: string
description: the constant value (only if applicable).
@@ -621,6 +519,54 @@ components:
comment:
type: string
description: the field comment.
DataType:
description: a known field data type.
type: object
properties:
type:
type: string
description: the type name.
example: UCH
isbits:
type: boolean
description: true when the length is in bits.
isadjustable:
type: boolean
description: whether the length is adjustable.
isignored:
type: boolean
description: whether the result is ignored.
length:
type: number
minimum: -1
maximum: 31
description: the field length in bytes (-1 for remainder, number
of bits when isbits is true).
result:
enum:
- void
- string
- number
- date
- time
- datetime
description: the result type.
divisor:
type: number
description: the divisor for numeric types (only if applicable, positive
for divisor, negative for reciprocal i.e. 1/-divisor).
precision:
type: number
description: the precision (number of fraction digits) when divisor is >1.
required:
- type
- isbits
- length
DataTypes:
type: array
description: the known field data types.
items:
$ref: '#/components/schemas/DataType'
Data:
required:
- global
@@ -630,6 +576,38 @@ components:
$ref: '#/components/schemas/Global'
additionalProperties:
$ref: '#/components/schemas/Circuit'
RawMessage:
type: object
description: raw message seen on the bus.
properties:
master:
$ref: '#/components/schemas/Symbols'
description: the last seen master data bytes (only with raw and if available).
slave:
$ref: '#/components/schemas/Symbols'
description: the last seen slave data bytes (only with raw and if available).
lastup:
minimum: 0
type: integer
description: the time in UTC seconds of the last update of the message (0
for never).
count:
type: number
description: number of times the master part was seen.
circuit:
type: string
description: name of the circuit in case of an already associated message definition.
name:
type: string
description: name of the message in case of an already associated message definition.
required:
- master
- count
RawMessages:
type: array
description: raw messages seen on the bus.
items:
$ref: '#/components/schemas/RawMessage'
responses:
BadRequest:
description: Invalid request parameters.
@@ -676,72 +654,80 @@ components:
name: exact
in: query
description: exact search for circuit/message name.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
verboseQuery:
name: verbose
in: query
description: include comments and field units.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
indexedQuery:
name: indexed
in: query
description: always return field indexes instead of names.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
numericQuery:
name: numeric
in: query
description: return numeric values of value list entries.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
valuenameQuery:
name: valuename
in: query
description: include value and name for named values.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
fullQuery:
name: full
in: query
description: include all available attributes.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
requiredQuery:
name: required
in: query
description: retrieve the data from the bus if not yet cached.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
writeQuery:
name: write
in: query
description: retrieve write messages in addition to read/poll messages.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
rawQuery:
name: raw
in: query
description: include raw master/slave data.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
defQuery:
name: def
in: query
description: include message and field definition.
allowEmptyValue: false
allowEmptyValue: true
schema:
type: boolean
defineQuery:
name: define
in: query
description: update/replace a message definition.
allowEmptyValue: false
schema:
type: string
description: message definition in CSV format.
userQuery:
name: user
in: query
@@ -756,4 +742,3 @@ components:
allowEmptyValue: false
schema:
type: string
+1 -1
View File
@@ -5,4 +5,4 @@ echo "ebusd=${version},${revision}" > versions.txt
echo "ebusd=${version},${revision}" > oldversions.txt
files=`find config/ -type f -or -type l`
../../src/lib/ebus/test/test_filereader $files|sed -e 's#^config/##' -e 's#^\([^ ]*\) #\1=#' -e 's# #,#g'|sort >> versions.txt
./oldtest_filereader $files|sed -e 's#^config/##' -e 's#^\([^ ]*\) #\1=#' -e 's# #,#g'|sort >> oldversions.txt
#./oldtest_filereader $files|sed -e 's#^config/##' -e 's#^\([^ ]*\) #\1=#' -e 's# #,#g'|sort >> oldversions.txt
+17 -15
View File
@@ -15,8 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
pwd
ls -la
keepbuilddir=
if [ "x$1" = "x--keepbuilddir" ]; then
keepbuilddir=1
@@ -80,16 +78,21 @@ else
fi
fi
echo
echo "*************"
echo " test"
echo "*************"
echo
testdie() {
echo "test failed"
exit 1
}
(cd src/lib/ebus/test && make test_data >/dev/null && ./test_data) || testdie
if [ -n "$RUNTEST" ]; then
echo
echo "*************"
echo " test"
echo "*************"
echo
testdie() {
echo "test failed"
exit 1
}
($RELEASE/usr/bin/ebusd -f -c src/lib/ebus/test -d /dev/null --checkconfig -i 10fe0900040000803e/ | egrep "received update-read broadcast test QQ=10: 0\.25$") || testdie
if [ "$RUNTEST" == "full" ]; then
(cd src/lib/ebus/test && make >/dev/null && ./test_filereader && ./test_data && ./test_message && ./test_symbol) || testdie
fi
fi
echo
echo "*************"
@@ -97,7 +100,6 @@ echo " pack"
echo "*************"
echo
mkdir -p $RELEASE/DEBIAN $RELEASE/etc/default $RELEASE/etc/logrotate.d || exit 1
rm $RELEASE/usr/bin/ebusfeed
mkdir -p $RELEASE/lib/systemd/system || exit 1
cp contrib/debian/systemd/ebusd.service $RELEASE/lib/systemd/system/ebusd.service || exit 1
mkdir -p $RELEASE/etc/init.d || exit 1
@@ -114,13 +116,13 @@ Architecture: $ARCH
Maintainer: John Baier <ebusd@ebusd.eu>
Homepage: https://github.com/john30/ebusd
Bugs: https://github.com/john30/ebusd/issues
Depends: logrotate, libstdc++6 (>= 4.8.1), libc6, libgcc1$extralibs
Depends: libstdc++6 (>= 4.8.1), libc6, libgcc1$extralibs
Recommends: logrotate
Description: eBUS daemon.
ebusd is a daemon for handling communication with eBUS devices connected to a
2-wire bus system.
EOF
cat <<EOF > $RELEASE/DEBIAN/dirs
/etc/ebusd
/etc/default
/etc/init.d
/etc/logrotate.d
+78 -47
View File
@@ -253,65 +253,87 @@ bool decodeType(const DataType* type, const SymbolString& input, size_t length,
return !first;
}
bool GrabbedMessage::dump(bool unknown, MessageMap* messages, bool first, bool decode, ostringstream* output,
bool isDirectMode) const {
bool GrabbedMessage::dump(bool unknown, MessageMap* messages, bool first, OutputFormat outputFormat,
ostringstream* output, bool isDirectMode) const {
Message* message = messages->find(m_lastMaster);
if (unknown && message) {
return false;
}
if (!first) {
*output << endl;
if (outputFormat & OF_JSON) {
*output << ",";
} else {
*output << endl;
}
}
symbol_t dstAddress = m_lastMaster[1];
*output << m_lastMaster.getStr();
if (dstAddress != BROADCAST && !isMaster(dstAddress)) {
*output << (isDirectMode ? " " : " / ") << m_lastSlave.getStr();
}
if (!isDirectMode) {
*output << " = " << m_count;
if (outputFormat & OF_JSON) {
*output << "\n{";
if (m_lastMaster.dumpJson(false, output)) {
*output << ", ";
if (dstAddress != BROADCAST && !isMaster(dstAddress) && m_lastSlave.dumpJson(false, output)) {
*output << ", ";
}
}
*output << "\"count\": " << static_cast<unsigned>(m_count);
*output << ", \"lastup\": " << setw(0) << dec << m_lastTime;
if (message) {
*output << ": " << message->getCircuit() << " " << message->getName();
*output << ", \"circuit\": \"" << message->getCircuit() << "\""
<< ", \"name\": \"" << message->getName() << "\"";
}
*output << "}";
} else {
*output << m_lastMaster.getStr();
if (dstAddress != BROADCAST && !isMaster(dstAddress)) {
*output << (isDirectMode ? " " : " / ") << m_lastSlave.getStr();
}
if (!isDirectMode) {
*output << " = " << m_count;
if (message) {
*output << ": " << message->getCircuit() << " " << message->getName();
}
}
}
if (decode) {
DataTypeList *types = DataTypeList::getInstance();
if (!types) {
return true;
if (!(outputFormat & OF_DEFINITION) || (outputFormat & OF_JSON)) {
return true;
}
DataTypeList *types = DataTypeList::getInstance();
if (!types) {
return true;
}
bool master = isMaster(dstAddress) || dstAddress == BROADCAST || m_lastSlave.getDataSize() <= 0;
size_t remain = master ? m_lastMaster.getDataSize() : m_lastSlave.getDataSize();
if (remain == 0) {
return true;
}
for (const auto& it : *types) {
const DataType* baseType = it.second;
if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored() || baseType->hasFlag(DUP)) { // skip bit and ignored types
continue;
}
bool master = isMaster(dstAddress) || dstAddress == BROADCAST || m_lastSlave.getDataSize() <= 0;
size_t remain = master ? m_lastMaster.getDataSize() : m_lastSlave.getDataSize();
if (remain == 0) {
return true;
size_t maxLength = baseType->getBitCount()/8;
bool firstOnly = maxLength >= 8;
if (maxLength > remain) {
maxLength = remain;
}
for (const auto& it : *types) {
const DataType* baseType = it.second;
if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored()) { // skip bit and ignored types
continue;
}
size_t maxLength = baseType->getBitCount()/8;
bool firstOnly = maxLength >= 8;
if (maxLength > remain) {
maxLength = remain;
}
if (baseType->isAdjustableLength()) {
for (size_t length = maxLength; length >= 1; length--) {
const DataType* type = types->get(baseType->getId(), length);
bool decoded;
if (master) {
decoded = decodeType(type, m_lastMaster, length, remain-length, firstOnly, output);
} else {
decoded = decodeType(type, m_lastSlave, length, remain-length, firstOnly, output);
}
if (decoded && firstOnly) {
break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes
}
}
} else if (maxLength > 0) {
if (baseType->isAdjustableLength()) {
for (size_t length = maxLength; length >= 1; length--) {
const DataType* type = types->get(baseType->getId(), length);
bool decoded;
if (master) {
decodeType(baseType, m_lastMaster, maxLength, remain-maxLength, false, output);
decoded = decodeType(type, m_lastMaster, length, remain-length, firstOnly, output);
} else {
decodeType(baseType, m_lastSlave, maxLength, remain-maxLength, false, output);
decoded = decodeType(type, m_lastSlave, length, remain-length, firstOnly, output);
}
if (decoded && firstOnly) {
break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes
}
}
} else if (maxLength > 0) {
if (master) {
decodeType(baseType, m_lastMaster, maxLength, remain-maxLength, false, output);
} else {
decodeType(baseType, m_lastSlave, maxLength, remain-maxLength, false, output);
}
}
}
@@ -425,6 +447,14 @@ void BusHandler::run() {
} while (isRunning());
}
#ifndef FALLTHROUGH
#if defined(__GNUC__) && __GNUC__ >= 7
#define FALLTHROUGH [[fallthrough]];
#else
#define FALLTHROUGH
#endif
#endif
result_t BusHandler::handleSymbol() {
unsigned int timeout = SYN_TIMEOUT;
symbol_t sendSymbol = ESC;
@@ -438,6 +468,7 @@ result_t BusHandler::handleSymbol() {
case bs_skip:
timeout = SYN_TIMEOUT;
FALLTHROUGH
case bs_ready:
if (m_currentRequest != nullptr) {
setState(bs_ready, RESULT_ERR_TIMEOUT); // just to be sure an old BusRequest is cleaned up
@@ -1601,10 +1632,10 @@ bool BusHandler::enableGrab(bool enable) {
return true;
}
void BusHandler::formatGrabResult(bool unknown, bool decode, ostringstream* output, bool isDirectMode,
void BusHandler::formatGrabResult(bool unknown, OutputFormat outputFormat, ostringstream* output, bool isDirectMode,
time_t since, time_t until) const {
if (!m_grabMessages) {
if (!isDirectMode) {
if (!isDirectMode && !(outputFormat & OF_JSON)) {
*output << "grab disabled";
}
return;
@@ -1615,7 +1646,7 @@ void BusHandler::formatGrabResult(bool unknown, bool decode, ostringstream* outp
|| (until > 0 && it.second.getLastTime() >= until)) {
continue;
}
if (it.second.dump(unknown, m_messages, first, decode, output, isDirectMode)) {
if (it.second.dump(unknown, m_messages, first, outputFormat, output, isDirectMode)) {
first = false;
}
}
+4 -4
View File
@@ -334,12 +334,12 @@ class GrabbedMessage {
* @param unknown whether to dump only if this message is unknown.
* @param messages the @a MessageMap instance for resolving known @a Message instances.
* @param first whether this is the first message to be added to the output.
* @param decode whether to add decoding hints.
* @param outputFormat the @a OutputFormat options to use.
* @param output the @a ostringstream to format the messages to.
* @param isDirectMode true for direct mode, false for grab command.
* @return whether the message was added to the output.
*/
bool dump(bool unknown, MessageMap* messages, bool first, bool decode, ostringstream* output,
bool dump(bool unknown, MessageMap* messages, bool first, OutputFormat outputFormat, ostringstream* output,
bool isDirectMode = false) const;
@@ -538,13 +538,13 @@ class BusHandler : public WaitThread {
/**
* Format the grabbed messages to the @a ostringstream.
* @param unknown whether to dump only unknown messages.
* @param decode whether to add decoding hints.
* @param outputFormat the @a OutputFormat options to use.
* @param output the @a ostringstream to format the messages to.
* @param isDirectMode true for direct mode, false for grab command.
* @param since the start time from which to add received messages (inclusive), or 0 for all.
* @param until the end time to which to add received messages (exclusive), or 0 for all.
*/
void formatGrabResult(bool unknown, bool decode, ostringstream* output, bool isDirectMode = false,
void formatGrabResult(bool unknown, OutputFormat outputFormat, ostringstream* output, bool isDirectMode = false,
time_t since = 0, time_t until = 0) const;
/**
+2 -2
View File
@@ -1388,10 +1388,10 @@ int main(int argc, char* argv[]) {
s_mainLoop = new MainLoop(opt, device, s_messageMap);
if (opt.injectMessages) {
BusHandler* busHandler = s_mainLoop->getBusHandler();
MasterSymbolString master;
SlaveSymbolString slave;
while (arg_index < argc) {
// add each passed message
MasterSymbolString master;
SlaveSymbolString slave;
if (!parseMessage(argv[arg_index++], false, &master, &slave)) {
continue;
}
+148 -20
View File
@@ -434,14 +434,14 @@ void MainLoop::run() {
}
if (settings.listenWithUnknown || settings.listenOnlyUnknown) {
if (m_busHandler->isGrabEnabled()) {
m_busHandler->formatGrabResult(true, false, &ostream, true, since, now);
m_busHandler->formatGrabResult(true, OF_NONE, &ostream, true, since, now);
} else {
m_busHandler->enableGrab(true); // needed for listening to all messages
}
}
} else if (settings.mode == cm_direct) {
if (m_busHandler->isGrabEnabled()) {
m_busHandler->formatGrabResult(false, false, &ostream, true, since, now);
m_busHandler->formatGrabResult(false, OF_NONE, &ostream, true, since, now);
}
}
// send result to client
@@ -607,7 +607,7 @@ result_t MainLoop::decodeMessage(const string &data, bool isHttp, bool* connecte
if (cmd == "G" || cmd == "GRAB") {
return executeGrab(args, ostream);
}
if (cmd == "DEFINE") {
if (cmd == "DEF" || cmd == "DEFINE") {
if (m_newlyDefinedMessages) {
return executeDefine(args, ostream);
}
@@ -921,8 +921,6 @@ result_t MainLoop::executeRead(const vector<string>& args, const string& levels,
Message* message;
result_t ret;
if (newDefinition) {
time_t now;
time(&now);
string errorDescription;
istringstream defstr("#\n" + args[argPos]); // ensure first line is not used for determining col names
m_newlyDefinedMessages->clear();
@@ -1256,7 +1254,7 @@ result_t MainLoop::parseHexAndSend(const vector<string>& args, size_t& argPos, b
result_t MainLoop::executeHex(const vector<string>& args, ostringstream* ostream) {
size_t argPos = 1;
result_t ret = parseHexAndSend(args, argPos, false, ostream);
if (argPos == args.size()) {
if (argPos != 0 && argPos == args.size()) {
return ret;
}
*ostream << "usage: hex [-s QQ] ZZPBSBNN[DD]*\n"
@@ -1641,7 +1639,7 @@ result_t MainLoop::executeGrab(const vector<string>& args, ostringstream* ostrea
}
}
if (!invalid) {
m_busHandler->formatGrabResult(onlyUnknown, decode, ostream);
m_busHandler->formatGrabResult(onlyUnknown, decode ? OF_DEFINITION : OF_NONE, ostream);
return RESULT_OK;
}
}
@@ -1677,7 +1675,7 @@ result_t MainLoop::executeDefine(const vector<string>& args, ostringstream* ostr
time(&now);
string errorDescription;
istringstream defstr("#\n" + args[argPos]); // ensure first line is not used for determining col names
return m_messages->readFromStream(&defstr, "temporary", now, true, nullptr, &errorDescription, replace);
return m_messages->readFromStream(&defstr, "tcp", now, true, nullptr, &errorDescription, replace);
}
@@ -1902,19 +1900,30 @@ result_t MainLoop::executeReload(const vector<string>& args, ostringstream* ostr
}
result_t MainLoop::executeInfo(const vector<string>& args, const string& user, ostringstream* ostream) {
if (args.size() == 0) {
*ostream << "usage: info\n"
" Report information about the daemon, the configuration, and seen devices.";
bool verbose = args.size() == 2 && args[1] == "verbose";
if (args.size() != 1 && !verbose) {
*ostream << "usage: info [verbose]\n"
" Report information about the daemon, configuration, seen participants, and the device.";
return RESULT_OK;
}
*ostream << "version: " << PACKAGE_STRING "." REVISION "\n";
if (!m_updateCheck.empty()) {
*ostream << "update check: " << m_updateCheck << "\n";
}
string info = m_device->getEnhancedInfos();
if (!info.empty()) {
*ostream << "device: " << info << "\n";
*ostream << "device: " << m_device->getName();
if (m_device->isEnhancedProto()) {
*ostream << ", enhanced";
}
if (m_device->isReadOnly()) {
*ostream << ", readonly";
}
if (verbose) {
string info = m_device->getEnhancedInfos();
if (!info.empty()) {
*ostream << ", " << info;
}
}
*ostream << "\n";
if (!user.empty()) {
*ostream << "user: " << user << "\n";
}
@@ -1962,8 +1971,8 @@ result_t MainLoop::executeHelp(ostringstream* ostream) {
*ostream << "usage:\n"
" read|r Read value(s): read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-c CIRCUIT] [-p PRIO] [-v|-V] [-n|-N]"
" [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n"
" Read by new defintion: read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-v|-V] [-n|-N] (if enabled)"
" [-i VALUE[;VALUE]*] -def DEFINITION\n"
" Read by new defintion: read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-v|-V] [-n|-N]"
" [-i VALUE[;VALUE]*] -def DEFINITION (if enabled)\n"
" Read hex message: read [-f] [-m SECONDS] [-s QQ] [-c CIRCUIT] -h ZZPBSBNN[DD]*\n"
" write|w Write value(s): write [-s QQ] [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n"
" Write by new def.: write [-s QQ] [-d ZZ] -def DEFINITION [VALUE[;VALUE]*] (if enabled)\n"
@@ -1975,7 +1984,7 @@ result_t MainLoop::executeHelp(ostringstream* ostream) {
" listen|l Listen for updates: listen [-v|-V] [-n|-N] [-u|-U] [stop]\n"
" direct Enter direct mode\n"
" state|s Report bus state\n"
" info|i Report information about the daemon, the configuration, and seen devices.\n"
" info|i Report information about the daemon, configuration, seen participants, and the device.\n"
" grab|g Grab messages: grab [stop]\n"
" Report the messages: grab result [all]\n"
" define Define new message: define [-r] DEFINITION\n"
@@ -2002,9 +2011,6 @@ bool parseBoolQuery(const string& value) {
}
result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostringstream* ostream) {
bool required = false, full = false, withWrite = false, raw = false;
bool withDefinition = false;
OutputFormat verbosity = OF_NAMES;
time_t maxAge = -1;
size_t argPos = 1;
string uri = args[argPos++];
@@ -2019,6 +2025,10 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
circuit = uri.substr(6, pos - 6);
name = uri.substr(pos + 1);
}
bool required = false, full = false, withWrite = false, raw = false;
bool withDefinition = false;
string newDefinition;
OutputFormat verbosity = OF_NAMES;
time_t since = 0;
size_t pollPriority = 0;
bool exact = false;
@@ -2072,6 +2082,18 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
raw = parseBoolQuery(value);
} else if (qname == "def") {
withDefinition = parseBoolQuery(value);
} else if (qname == "define") {
if (!m_newlyDefinedMessages || circuit.empty() || name.empty() || value.empty()) {
ret = RESULT_ERR_INVALID_ARG;
break;
}
size_t comma = value.find(',');
if (comma == string::npos || comma == 0
|| value.find(circuit+","+name+",") != comma+1) { // ensure same circuit+name
ret = RESULT_ERR_INVALID_ARG;
break;
}
newDefinition = value;
} else if (qname == "user") {
user = value;
} else if (qname == "secret") {
@@ -2091,6 +2113,11 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
time_t now;
time(&now);
time_t maxLastUp = 0;
if (ret == RESULT_OK && !newDefinition.empty()) {
string errorDescription;
istringstream defstr("#\n" + newDefinition); // ensure first line is not used for determining col names
ret = m_messages->readFromStream(&defstr, "http", now, true, nullptr, &errorDescription, true);
}
if (ret == RESULT_OK) {
bool first = true;
verbosity |= OF_JSON | (full ? OF_ALL_ATTRS : OF_NONE) | (withDefinition ? OF_DEFINITION : OF_NONE);
@@ -2192,6 +2219,107 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
return formatHttpResult(ret, type, ostream);
} // request for "/data..."
if (uri == "/datatypes") {
*ostream << "[";
OutputFormat verbosity = OF_NAMES|OF_JSON|OF_ALL_ATTRS;
DataTypeList::getInstance()->dump(verbosity, true, ostream);
*ostream << "\n]";
type = 6;
*connected = false;
return formatHttpResult(ret, type, ostream);
}
if (uri == "/raw") {
time_t since = 0, until = 0;
bool onlyUnknown = false;
if (args.size() > argPos) {
string query = args[argPos];
istringstream stream(query);
string token;
while (getline(stream, token, '&')) {
size_t pos = token.find('=');
string qname, value;
if (pos != string::npos) {
qname = token.substr(0, pos);
value = token.substr(pos + 1);
} else {
qname = token;
}
if (qname == "since") {
since = parseInt(value.c_str(), 10, 0, 0xffffffff, &ret);
} else if (qname == "unknown") {
onlyUnknown = parseBoolQuery(value);
}
if (ret != RESULT_OK) {
break;
}
}
}
if (ret == RESULT_OK) {
*ostream << "[";
if (since > 0) {
time_t now;
time(&now);
until = now-1;
}
m_busHandler->formatGrabResult(onlyUnknown, OF_JSON, ostream, false, since, until);
*ostream << "\n]";
type = 6;
}
*connected = false;
return formatHttpResult(ret, type, ostream);
}
if (uri == "/decode") {
string def;
string raw;
if (args.size() > argPos) {
string query = args[argPos];
istringstream stream(query);
string token;
while (getline(stream, token, '&')) {
size_t pos = token.find('=');
string qname, value;
if (pos != string::npos) {
qname = token.substr(0, pos);
value = token.substr(pos + 1);
} else {
qname = token;
}
if (qname == "def") {
def = value;
} else if (qname == "raw") {
raw = value;
}
if (ret != RESULT_OK) {
break;
}
}
}
if (ret == RESULT_OK) {
time_t now;
time(&now);
istringstream defstr("#\n" + def); // ensure first line is not used for determining col names
string errorDescription;
DataFieldTemplates* templates = getTemplates("*");
LoadableDataFieldSet fields("", templates);
ret = fields.readFromStream(&defstr, "temporary", now, true, nullptr, &errorDescription);
if (ret == RESULT_OK) {
const SingleDataField* field = fields[0];
SlaveSymbolString slave;
slave.push_back(0); // dummy length
ret = slave.parseHex(raw);
if (ret == RESULT_OK) {
slave.adjustHeader();
ret = field->read(slave, 0, false, nullptr, 0, OF_JSON|OF_SHORT, 0, ostream);
}
}
type = 6;
}
*connected = false;
return formatHttpResult(ret, type, ostream);
}
if (uri.length() < 1 || uri[0] != '/' || uri.find("//") != string::npos || uri.find("..") != string::npos) {
ret = RESULT_ERR_INVALID_ARG;
} else {
+8 -2
View File
@@ -46,6 +46,7 @@ using std::dec;
#define O_KEYF (O_CERT+1)
#define O_KEPA (O_KEYF+1)
#define O_INSE (O_KEPA+1)
#define O_VERB (O_INSE+1)
/** the definition of the MQTT arguments. */
static const struct argp_option g_mqtt_argp_options[] = {
@@ -60,6 +61,7 @@ static const struct argp_option g_mqtt_argp_options[] = {
"Use MQTT TOPIC (prefix before /%circuit/%name or complete format) [ebusd]", 0 },
{"mqttretain", O_RETA, nullptr, 0, "Retain all topics instead of only selected global ones", 0 },
{"mqttjson", O_JSON, nullptr, 0, "Publish in JSON format instead of strings", 0 },
{"mqttverbose", O_VERB, nullptr, 0, "Publish all available attributes", 0 },
#if (LIBMOSQUITTO_VERSION_NUMBER >= 1003001)
{"mqttlog", O_LOGL, nullptr, 0, "Log library events", 0 },
#endif
@@ -75,7 +77,7 @@ static const struct argp_option g_mqtt_argp_options[] = {
{"mqttcert", O_CERT, "CERTFILE", 0, "Use CERTFILE for MQTT TLS client certificate (no default)", 0 },
{"mqttkey", O_KEYF, "KEYFILE", 0, "Use KEYFILE for MQTT TLS client certificate (no default)", 0 },
{"mqttkeypass", O_KEPA, "PASSWORD", 0, "Use PASSWORD for the encrypted KEYFILE (no default)", 0 },
{"mqttinsecure", O_INSE, nullptr, 0, "Allow insecure TLS connection (e.g. using a self signed certificate)", 0 },
{"mqttinsecure", O_INSE, nullptr, 0, "Allow insecure TLS connection (e.g. using a self signed certificate)", 0 },
#endif
{nullptr, 0, nullptr, 0, nullptr, 0 },
@@ -189,6 +191,10 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
g_publishFormat |= OF_JSON|OF_NAMES;
break;
case O_VERB: // --mqttverbose
g_publishFormat |= OF_NAMES|OF_UNITS|OF_COMMENTS|OF_ALL_ATTRS;
break;
#if (LIBMOSQUITTO_VERSION_NUMBER >= 1003001)
case O_LOGL:
g_logFromLib = true;
@@ -909,7 +915,7 @@ void MqttHandler::publishMessage(const Message* message, ostringstream* updates,
publishTopic(getTopic(message), updates->str());
return;
}
if (json) {
if (json && !(outputFormat & OF_ALL_ATTRS)) {
outputFormat |= OF_SHORT;
}
for (size_t index = 0; index < message->getFieldCount(); index++) {
+76 -31
View File
@@ -45,7 +45,12 @@ using std::endl;
bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
if (outputFormat & OF_JSON) {
*output << "\"type\": \"" << m_id << "\", \"isbits\": "
<< (getBitCount() < 8 ? "true" : "false") << ", \"length\": ";
<< (getBitCount() < 8 ? "true" : "false");
if (outputFormat & OF_ALL_ATTRS) {
*output << ", \"isadjustable\": " << (isAdjustableLength() ? "true" : "false");
*output << ", \"isignored\": " << (isIgnored() ? "true" : "false");
}
*output << ", \"length\": ";
if (isAdjustableLength() && length == REMAIN_LEN) {
*output << "-1";
} else {
@@ -54,10 +59,11 @@ bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor
} else {
*output << m_id;
if (isAdjustableLength()) {
*output << LENGTH_SEPARATOR;
if (length == REMAIN_LEN) {
*output << ":*";
*output << "*";
} else {
*output << ":" << static_cast<unsigned>(length);
*output << static_cast<unsigned>(length);
}
}
if (appendDivisor) {
@@ -68,6 +74,14 @@ bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor
}
bool StringDataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
DataType::dump(outputFormat, length, appendDivisor, output);
if ((outputFormat & OF_JSON) && (outputFormat & OF_ALL_ATTRS)) {
*output << ", \"result\": \"" << (isIgnored() ? "void" : "string") << "\"";
}
return false;
}
result_t StringDataType::readRawValue(size_t, size_t, const SymbolString&, unsigned int*) const {
return RESULT_EMPTY;
}
@@ -203,6 +217,14 @@ result_t StringDataType::writeSymbols(size_t offset, size_t length, istringstrea
}
bool DateTimeDataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
DataType::dump(outputFormat, length, appendDivisor, output);
if ((outputFormat & OF_JSON) && (outputFormat & OF_ALL_ATTRS)) {
*output << ", \"result\": \"" << (hasDate() ? hasTime() ? "datetime" : "date" : "time") << "\"";
}
return false;
}
result_t DateTimeDataType::readRawValue(size_t, size_t, const SymbolString&, unsigned int*) const {
return RESULT_EMPTY;
}
@@ -572,25 +594,32 @@ bool NumberDataType::dump(OutputFormat outputFormat, size_t length, bool appendD
} else {
DataType::dump(outputFormat, length, appendDivisor, output);
}
if ((outputFormat & OF_JSON) && (outputFormat & OF_ALL_ATTRS)) {
*output << ", \"result\": \"number\"";
}
if (!appendDivisor) {
return false;
}
bool ret = false;
if (m_baseType) {
if (m_baseType->m_divisor != m_divisor) {
if (outputFormat & OF_JSON) {
*output << ", \"divisor\": ";
}
*output << (m_divisor / m_baseType->m_divisor);
return true;
ret = true;
}
} else if (m_divisor != 1) {
if (outputFormat & OF_JSON) {
*output << ", \"divisor\": ";
}
*output << m_divisor;
return true;
ret = true;
}
return false;
if (ret && (outputFormat & OF_JSON) && (outputFormat & OF_ALL_ATTRS)) {
*output << ", \"precision\": " << static_cast<unsigned>(getPrecision());
}
return ret;
}
result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataType** derived) const {
@@ -985,16 +1014,18 @@ DataTypeList::DataTypeList() {
// date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99,
// WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
add(new DateTimeDataType("BDA", 32, BCD, 0xff, true, false, 0));
add(new DateTimeDataType("BDA:4", 32, BCD|DUP, 0xff, true, false, 0));
// date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99, replacement 0xff)
add(new DateTimeDataType("BDA", 24, BCD, 0xff, true, false, 0));
add(new DateTimeDataType("BDA:3", 24, BCD, 0xff, true, false, 0));
// date with zero-based weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WZ,0x00 - 0x31,0x12,WZ,0x99,
// WZ is zero-based weekday Mon=0x00 - Sun=0x06, replacement 0xff)
add(new DateTimeDataType("BDZ", 32, BCD|SPE, 0xff, true, false, 0));
// date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x1f,0x0c,WW,0x63,
// WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
add(new DateTimeDataType("HDA", 32, 0, 0xff, true, false, 0));
add(new DateTimeDataType("HDA:4", 32, DUP, 0xff, true, false, 0));
// date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63, replacement 0xff)
add(new DateTimeDataType("HDA", 24, 0, 0xff, true, false, 0));
add(new DateTimeDataType("HDA:3", 24, 0, 0xff, true, false, 0));
// date, days since 01.01.1900, 01.01.1900 - 06.06.2079 (0x00,0x00 - 0xff,0xff)
add(new DateTimeDataType("DAY", 16, 0, 0xff, true, false, 0));
// date+time in minutes since 01.01.2009, 01.01.2009 - 31.12.2099 (0x00,0x00,0x00,0x00 - 0x02,0xda,0x4e,0x1f)
@@ -1022,13 +1053,15 @@ DataTypeList::DataTypeList() {
add(new NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1)); // weekday, "Mon" - "Sun" (0x00 - 0x06) [eBUS type]
add(new NumberDataType("HDY", 8, DAY, 0x00, 1, 7, 1)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
add(new NumberDataType("BCD", 8, BCD, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99
add(new NumberDataType("BCD", 16, BCD, 0xffff, 0, 9999, 1)); // unsigned decimal in BCD, 0 - 9999
add(new NumberDataType("BCD", 24, BCD, 0xffffff, 0, 999999, 1)); // unsigned decimal in BCD, 0 - 999999
add(new NumberDataType("BCD", 32, BCD, 0xffffffff, 0, 99999999, 1)); // unsigned decimal in BCD, 0 - 99999999
add(new NumberDataType("BCD:1", 8, BCD|DUP, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99
add(new NumberDataType("BCD:2", 16, BCD, 0xffff, 0, 9999, 1)); // unsigned decimal in BCD, 0 - 9999
add(new NumberDataType("BCD:3", 24, BCD, 0xffffff, 0, 999999, 1)); // unsigned decimal in BCD, 0 - 999999
add(new NumberDataType("BCD:4", 32, BCD, 0xffffffff, 0, 99999999, 1)); // unsigned decimal in BCD, 0 - 99999999
add(new NumberDataType("HCD", 32, HCD|BCD|REQ, 0, 0, 99999999, 1)); // unsigned decimal in HCD, 0 - 99999999
add(new NumberDataType("HCD", 8, HCD|BCD|REQ, 0, 0, 99, 1)); // unsigned decimal in HCD, 0 - 99
add(new NumberDataType("HCD", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // unsigned decimal in HCD, 0 - 9999
add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999
add(new NumberDataType("HCD:4", 32, HCD|BCD|REQ|DUP, 0, 0, 99999999, 1)); // unsigned decimal in HCD, 0 - 99999999
add(new NumberDataType("HCD:1", 8, HCD|BCD|REQ, 0, 0, 99, 1)); // unsigned decimal in HCD, 0 - 99
add(new NumberDataType("HCD:2", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // unsigned decimal in HCD, 0 - 9999
add(new NumberDataType("HCD:3", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999
add(new NumberDataType("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
// unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
@@ -1076,36 +1109,48 @@ DataTypeList::DataTypeList() {
add(new NumberDataType("BI4", 4, ADJ|REQ, 0, 4, 1)); // bit 4 (up to 4 bits until bit 7)
add(new NumberDataType("BI5", 3, ADJ|REQ, 0, 5, 1)); // bit 5 (up to 3 bits until bit 7)
add(new NumberDataType("BI6", 2, ADJ|REQ, 0, 6, 1)); // bit 6 (up to 2 bits until bit 7)
add(new NumberDataType("BI7", 1, ADJ|REQ, 0, 7, 1)); // bit 7
add(new NumberDataType("BI7", 1, REQ, 0, 7, 1)); // bit 7
}
DataTypeList* DataTypeList::getInstance() {
return &s_instance;
}
void DataTypeList::dump(OutputFormat outputFormat, bool appendDivisor, ostream* output) const {
bool json = outputFormat & OF_JSON;
string sep = "\n";
for (const auto &it: m_typesById) {
const DataType *dataType = it.second;
if (dataType->hasFlag(DUP)) {
continue;
}
if (json) {
*output << sep << " {";
}
if ((dataType->getBitCount() % 8) != 0) {
dataType->dump(outputFormat, dataType->getBitCount(), appendDivisor, output);
} else {
dataType->dump(outputFormat, dataType->getBitCount() / 8, appendDivisor, output);
}
if (json) {
*output << "}";
sep = ",\n";
} else {
*output << "\n";
}
}
}
void DataTypeList::clear() {
for (auto& it : m_cleanupTypes) {
delete it;
}
m_cleanupTypes.clear();
m_typesByIdLength.clear();
m_typesById.clear();
}
result_t DataTypeList::add(const DataType* dataType) {
if (!dataType->isAdjustableLength()) {
ostringstream str;
size_t bitCount = dataType->getBitCount();
str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount >= 8?bitCount/8:bitCount);
if (m_typesByIdLength.find(str.str()) != m_typesByIdLength.end()) {
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
}
m_typesByIdLength[str.str()] = dataType;
if (m_typesById.find(dataType->getId()) != m_typesById.end()) {
m_cleanupTypes.push_back(dataType);
return RESULT_OK; // only store first one as default
}
} else if (m_typesById.find(dataType->getId()) != m_typesById.end()) {
if (m_typesById.find(dataType->getId()) != m_typesById.end()) {
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
}
m_typesById[dataType->getId()] = dataType;
@@ -1117,8 +1162,8 @@ const DataType* DataTypeList::get(const string& id, size_t length) const {
if (length > 0) {
ostringstream str;
str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length);
auto it = m_typesByIdLength.find(str.str());
if (it != m_typesByIdLength.end()) {
auto it = m_typesById.find(str.str());
if (it != m_typesById.end()) {
return it->second;
}
}
+20 -10
View File
@@ -178,9 +178,8 @@ enum PartType {
/** bit flag for @a DataType: special marker for certain types. */
#define SPE 0x800
/** bit flag for @a DataType: marker for a constant value. */
#define CON 0x1000
/** bit flag for @a DataType: stored duplicate for backwards compatibility, not to be traversed in lists any more. */
#define DUP 0x1000
/**
* Base class for all kinds of data types.
@@ -326,6 +325,9 @@ class StringDataType : public DataType {
*/
virtual ~StringDataType() {}
// @copydoc
bool dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const override;
// @copydoc
result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const override;
@@ -370,6 +372,9 @@ class DateTimeDataType : public DataType {
*/
virtual ~DateTimeDataType() {}
// @copydoc
bool dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const override;
/**
* @return true if date part is present.
*/
@@ -429,7 +434,7 @@ class NumberDataType : public DataType {
NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
unsigned int minValue, unsigned int maxValue, int divisor,
const NumberDataType* baseType = nullptr)
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor),
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor==0 ? 1 : divisor),
m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(baseType) {}
/**
@@ -444,7 +449,7 @@ class NumberDataType : public DataType {
*/
NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
int16_t firstBit, int divisor, const NumberDataType* baseType = nullptr)
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor),
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor==0 ? 1 : divisor),
m_precision(0), m_firstBit(firstBit), m_baseType(baseType) {}
/**
@@ -570,6 +575,14 @@ class DataTypeList {
*/
static DataTypeList* getInstance();
/**
* Dump the type list optionally including the divisor to the output.
* @param outputFormat the @a OutputFormat options.
* @param appendDivisor whether to append the divisor (if available).
* @param output the @a ostream to dump to.
*/
void dump(OutputFormat outputFormat, bool appendDivisor, ostream* output) const;
/**
* Removes all @a DataType instances.
*/
@@ -611,12 +624,9 @@ class DataTypeList {
map<string, const DataType*>::const_iterator end() const { return m_typesById.end(); }
private:
/** the known @a DataType instances by ID only. */
map<string, const DataType*> m_typesById;
/** the known @a DataType instances by ID and length (i.e. "ID:BITS").
/** the known @a DataType instances by ID (e.g. "ID:BITS" or just "ID").
* Note: adjustable length types are stored by ID only. */
map<string, const DataType*> m_typesByIdLength;
map<string, const DataType*> m_typesById;
/** the @a DataType instances to cleanup. */
list<const DataType*> m_cleanupTypes;
+11 -25
View File
@@ -935,20 +935,6 @@ void Message::dumpField(const string& fieldName, bool withConditions, OutputForm
dumpAttribute(false, outputFormat, fieldName, output);
}
void addData(const SymbolString& data, ostringstream* output) {
if (data.size() == 0) {
return;
}
*output << ",\n \"" << (data.isMaster() ? "master" : "slave") << "\": [";
for (size_t pos = 0; pos < data.size(); pos++) {
if (pos > 0) {
*output << ", ";
}
*output << dec << static_cast<unsigned>(data[pos]);
}
*output << "]";
}
void Message::decodeJson(bool leadingSeparator, bool appendDirectionCondition, bool withData, bool addRaw,
OutputFormat outputFormat, ostringstream* output) const {
outputFormat |= OF_JSON;
@@ -1005,8 +991,8 @@ void Message::decodeJson(bool leadingSeparator, bool appendDirectionCondition, b
appendAttributes(outputFormat, output);
if (hasData) {
if (addRaw) {
addData(m_lastMasterData, output);
addData(m_lastSlaveData, output);
m_lastMasterData.dumpJson(true, output);
m_lastSlaveData.dumpJson(true, output);
*output << dec;
}
size_t pos = (size_t)output->tellp();
@@ -1884,27 +1870,27 @@ void MessageMap::remove(Message* message) {
const auto keyIt = m_messagesByKey.find(key);
bool deleted = false;
if (keyIt != m_messagesByKey.end()) {
vector<Message*> messages = keyIt->second;
for (auto it = messages.begin(); it != messages.end(); ) {
vector<Message*>* messages = &keyIt->second;
for (auto it = messages->begin(); it != messages->end(); ) {
Message* other = *it;
if (other == message) {
if (!deleted) {
deleted = true;
delete(other);
}
messages.erase(it);
it = messages->erase(it);
} else {
++it;
}
}
if (messages.empty()) {
if (messages->empty()) {
m_messagesByKey.erase(keyIt);
}
}
bool storedByName = false;
for (auto nameIt = m_messagesByName.begin(); nameIt != m_messagesByName.end(); ) {
vector<Message*> messages = nameIt->second;
for (auto it = messages.begin(); it != messages.end(); ) {
vector<Message*>* messages = &nameIt->second;
for (auto it = messages->begin(); it != messages->end(); ) {
Message* other = *it;
if (other == message) {
storedByName = true;
@@ -1912,13 +1898,13 @@ void MessageMap::remove(Message* message) {
deleted = true;
delete(other);
}
messages.erase(it);
it = messages->erase(it);
} else {
++it;
}
}
if (messages.empty()) {
m_messagesByName.erase(nameIt);
if (messages->empty()) {
nameIt = m_messagesByName.erase(nameIt);
} else {
++nameIt;
}
+5 -1
View File
@@ -122,7 +122,11 @@ class Message : public AttributedItem {
/**
* Destructor.
*/
virtual ~Message() { if (m_deleteData) { delete m_data; } }
virtual ~Message() {
if (m_deleteData) {
delete m_data;
}
}
/**
* Calculate the key for the ID.
+19
View File
@@ -28,6 +28,7 @@ namespace ebusd {
using std::ostringstream;
using std::nouppercase;
using std::setw;
using std::dec;
using std::hex;
using std::setfill;
@@ -157,6 +158,24 @@ const string SymbolString::getStr(size_t skipFirstSymbols) const {
return sstr.str();
}
bool SymbolString::dumpJson(bool withSeparator, ostringstream* output) const {
if (size() == 0) {
return false;
}
if (withSeparator) {
*output << ",\n ";
}
*output << "\"" << (isMaster() ? "master" : "slave") << "\": [";
for (size_t pos = 0; pos < size(); pos++) {
if (pos > 0) {
*output << ", ";
}
*output << dec << static_cast<unsigned>(m_data[pos]);
}
*output << "]";
return true;
}
symbol_t SymbolString::calcCrc() const {
symbol_t crc = 0;
for (size_t i = 0; i < m_data.size(); i++) {
+9
View File
@@ -67,6 +67,7 @@ namespace ebusd {
using std::string;
using std::vector;
using std::ostringstream;
/** the base type for symbols sent to/from the eBUS. */
typedef unsigned char symbol_t;
@@ -158,6 +159,14 @@ class SymbolString {
*/
const string getStr(size_t skipFirstSymbols = 0) const;
/**
* Dump the data in JSON format to the output.
* @param withSeparator true to prepend the field separator.
* @param output the @a ostringstream to format the messages to.
* @return true if something was written to the output.
*/
bool dumpJson(bool withSeparator, ostringstream* output) const;
/**
* Return a reference to the symbol at the specified index.
* @param index the index of the symbol to return.
+2
View File
@@ -0,0 +1,2 @@
#
b,broadcast,test,,,fe,0900,,,,EXP
1 #
2 b,broadcast,test,,,fe,0900,,,,EXP
+16 -16
View File
@@ -154,22 +154,22 @@ int main() {
{"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "dC" },
{"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" },
{"r,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8", "ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127", "09003231303734353030;09313030303237373930;09303030303030303030;024E38", "dC" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61", "ff08b509030d6900", "03138040", "d" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60", "ff08b509030d6900", "0313ffbf", "d" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61", "ff08b509030d6900", "03137fff", "d" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60", "ff08b509030d6900", "03137fbf", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B71", "ff08b509030d6a00", "0213ff", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B71", "ff08b509030d6a00", "0213bf", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B70", "ff08b509030d6a00", "02137f", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B70", "ff08b509030d6a00", "02133f", "d" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61", "ff08b509060e6900138040", "00", "di" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60", "ff08b509060e6900138000", "00", "di" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61", "ff08b509060e6900130040", "00", "di" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60", "ff08b509060e6900130000", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B71", "ff08b509050e6a0013c0", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B71", "ff08b509050e6a001380", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B70", "ff08b509050e6a001340", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B70", "ff08b509050e6a001300", "00", "di" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61", "ff08b509030d6900", "03138040", "d" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60", "ff08b509030d6900", "0313ffbf", "d" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61", "ff08b509030d6900", "03137fff", "d" },
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60", "ff08b509030d6900", "03137fbf", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B61;B71", "ff08b509030d6a00", "0213ff", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B60;B71", "ff08b509030d6a00", "0213bf", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B61;B70", "ff08b509030d6a00", "02137f", "d" },
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B60;B70", "ff08b509030d6a00", "02133f", "d" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61", "ff08b509060e6900138040", "00", "di" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60", "ff08b509060e6900138000", "00", "di" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61", "ff08b509060e6900130040", "00", "di" },
{"w,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60", "ff08b509060e6900130000", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B61;B71", "ff08b509050e6a0013c0", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B60;B71", "ff08b509050e6a001380", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B61;B70", "ff08b509050e6a001340", "00", "di" },
{"w,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7,0=B70;1=B71", "1.9;B60;B70", "ff08b509050e6a001300", "00", "di" },
{"w,,x,,,,,,,,IGN:1,,,,b0,,BI0:1,,,,b1,,BI1:1,,,,b2,,BI2:1,,,,,,IGN:1,,,,c0,,BI0:1,,,,c1,,BI1:1,,,,c2,,BI2:1", "1;1;1;0;0;0", "ff08b509050e00070000", "00", "di" },
{"w,,x,,,,,,,,IGN:1,,,,b0,,BI0:1,,,,b1,,BI1:1,,,,b2,,BI2:1,,,,,,IGN:1,,,,c0,,BI0:1,,,,c1,,BI1:1,,,,c2,,BI2:1", "1;0;0;0;0;1", "ff08b509050e00010004", "00", "di" },
{"w,,x,,,,,,,,IGN:1,,,,b0,,BI0:1,,,,b1,,BI1:1,,,,b2,,BI2:1,,,,,,IGN:1,,,,c0,,BI0:1,,,,c1,,BI1:1,,,,c2,,BI2:1", "0;0;1;0;1;1", "ff08b509050e00040006", "00", "di" },
-7
View File
@@ -1,20 +1,13 @@
set(ebusctl_SOURCES ebusctl.cpp)
set(ebusfeed_SOURCES ebusfeed.cpp)
set(ebuspicloader_SOURCES ebuspicloader.cpp intelhex/intelhexclass.cpp)
if(HAVE_CONTRIB)
set(ebusfeed_LIBS ${ebusfeed_LIBS} ebuscontrib)
endif(HAVE_CONTRIB)
include_directories(../lib/ebus)
include_directories(../lib/utils)
include_directories(intelhex)
add_executable(ebusctl ${ebusctl_SOURCES})
add_executable(ebusfeed ${ebusfeed_SOURCES})
add_executable(ebuspicloader ${ebuspicloader_SOURCES})
target_link_libraries(ebusctl utils ebus ${LIB_ARGP} ${ebusctl_LIBS})
target_link_libraries(ebusfeed ebus ${LIB_ARGP} ${ebusfeed_LIBS})
target_link_libraries(ebuspicloader ${LIB_ARGP})
install(TARGETS ebusctl ebuspicloader EXPORT ebusd DESTINATION usr/bin)
-9
View File
@@ -2,22 +2,13 @@ AM_CXXFLAGS = -I$(top_srcdir)/src \
-isystem$(top_srcdir)
bin_PROGRAMS = ebusctl \
ebusfeed \
ebuspicloader
ebusctl_SOURCES = ebusctl.cpp
ebusctl_LDADD = ../lib/utils/libutils.a
ebusfeed_SOURCES = ebusfeed.cpp
ebusfeed_LDADD = ../lib/utils/libutils.a \
../lib/ebus/libebus.a
ebuspicloader_SOURCES = ebuspicloader.cpp intelhex/intelhexclass.cpp
if CONTRIB
ebusfeed_LDADD += ../lib/ebus/contrib/libebuscontrib.a
endif
distclean-local:
-rm -f Makefile.in
-rm -rf .libs
-9
View File
@@ -63,15 +63,6 @@ EOF
./src/ebusd/ebusd -c contrib/etc/ebusd --checkconfig >/dev/null
rm -f contrib/etc/ebusd/bad.csv
echo > dump
./src/tools/ebusfeed -d tcp:127.0.0.1:8876 -t 10000 dump >/dev/null 2>/dev/null
./src/tools/ebusfeed -d tcp:127.0.0.1:99999 dump >/dev/null 2>/dev/null
./src/tools/ebusfeed -d udp:127.0.0.1:8876 -t 10000 dump >/dev/null 2>/dev/null
./src/tools/ebusfeed -d udp:127.0.0.1:8876 -t 10000 nonexistdump >/dev/null 2>/dev/null
./src/tools/ebusfeed -d "" >/dev/null 2>/dev/null
./src/tools/ebusfeed -t 1 >/dev/null 2>/dev/null
./src/tools/ebusfeed "" >/dev/null 2>/dev/null
./src/tools/ebusfeed 1 2 >/dev/null 2>/dev/null
./src/tools/ebusfeed -x >/dev/null 2>/dev/null
./src/tools/ebusctl -s testserver -p 100000 >/dev/null 2>/dev/null
./src/tools/ebusctl -s "" >/dev/null 2>/dev/null
./src/tools/ebusctl -p "" >/dev/null 2>/dev/null