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 ## Bug Fixes
* fix for escaping double quote in CSV format * fix for escaping double quote in CSV format
* adjusted helper shell scripts and Munin plugin to newer netcat * adjusted helper shell scripts and Munin plugin to newer netcat
* fix for weekday in BDA data type (for sending only) * 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 ## Features
* added DTM and BDZ data types * 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) # 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> # Contributor: Milan Knizek <knizek volny cz>
# Usage: makepkg # Usage: makepkg
pkgname=ebusd pkgname=ebusd
pkgver=21.2 pkgver=21.3
pkgrel=1 pkgrel=1
pkgdesc="ebusd, the daemon for communication with eBUS heating systems." pkgdesc="ebusd, the daemon for communication with eBUS heating systems."
arch=('i686' 'x86_64' 'armv6h' 'armv7h' 'aarch64') arch=('i686' 'x86_64' 'armv6h' 'armv7h' 'aarch64')
+1 -1
View File
@@ -3,7 +3,7 @@
# Usage: makepkg -p PKGBUILD.git # Usage: makepkg -p PKGBUILD.git
pkgname=ebusd-git pkgname=ebusd-git
_gitname=ebusd _gitname=ebusd
pkgver=21.2 pkgver=21.3
pkgrel=1 pkgrel=1
pkgdesc="ebusd, the daemon for communication with eBUS heating systems." pkgdesc="ebusd, the daemon for communication with eBUS heating systems."
arch=('i686' 'x86_64' 'armv6h' 'armv7h' 'aarch64') 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 \ RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \ libmosquitto-dev libstdc++6 libc6 libgcc1 \
@@ -9,25 +10,34 @@ RUN apt-get update && apt-get install -y \
WORKDIR /build WORKDIR /build
ENV EBUSD_ARCH amd64 ARG TARGETARCH
ENV EBUSD_VERSION 21.2 ARG TARGETVARIANT
ARG EBUSD_VERSION
RUN git clone https://github.com/john30/ebusd.git /build \ ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
&& ./make_debian.sh 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 \ 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/* && rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu" LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2 ARG TARGETARCH
ENV EBUSD_ARCH amd64 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" LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}-devel"
@@ -39,6 +49,6 @@ RUN dpkg -i ebusd.deb \
EXPOSE 8888 EXPOSE 8888
COPY docker-entrypoint.sh / COPY --from=build /build/contrib/docker/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"] ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"] 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 \ RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \ libmosquitto-dev libstdc++6 libc6 libgcc1 \
@@ -9,29 +10,38 @@ RUN apt-get update && apt-get install -y \
WORKDIR /build WORKDIR /build
ENV EBUSD_ARCH amd64 ARG TARGETARCH
ENV EBUSD_VERSION 21.2 ARG TARGETVARIANT
ARG EBUSD_VERSION
RUN git clone https://github.com/john30/ebusd.git /build \ ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
&& ./make_debian.sh 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 \ 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/* && rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu" LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION 21.2 ARG TARGETARCH
ENV EBUSD_ARCH amd64 ARG TARGETVARIANT
ARG EBUSD_VERSION
ARG EBUSD_IMAGE
ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
ENV EBUSD_VERSION $EBUSD_VERSION
LABEL version "${EBUSD_VERSION}-${EBUSD_ARCH}" 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 \ RUN dpkg -i ebusd.deb \
&& ebusd -V \ && ebusd -V \
@@ -39,6 +49,6 @@ RUN dpkg -i ebusd.deb \
EXPOSE 8888 EXPOSE 8888
COPY docker-entrypoint.sh / COPY contrib/docker/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"] ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"] 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% ARG BASE_IMAGE
FROM %BASE_IMAGE% as build
%QEMU_FROM_COPY% FROM $BASE_IMAGE as build
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
libmosquitto-dev libstdc++6 libc6 libgcc1 \ libmosquitto-dev libstdc++6 libc6 libgcc1 \
curl \ curl \
@@ -9,36 +10,45 @@ RUN apt-get update && apt-get install -y \
WORKDIR /build WORKDIR /build
ENV EBUSD_ARCH %EBUSD_ARCH% ARG TARGETARCH
ENV EBUSD_VERSION %EBUSD_VERSION% ARG TARGETVARIANT
ARG EBUSD_VERSION
RUN git clone https://github.com/john30/ebusd.git /build \ ENV EBUSD_ARCH $TARGETARCH$TARGETVARIANT
&& %EBUSD_MAKE% ENV EBUSD_VERSION $EBUSD_VERSION
ADD . /build
RUN %EBUSD_MAKE%
%EBUSD_UPLOAD_LINES% %EBUSD_UPLOAD_LINES%
FROM %BASE_IMAGE%-slim FROM $BASE_IMAGE-slim as image
%QEMU_FROM_COPY%
RUN apt-get update && apt-get install -y \ 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/* && rm -rf /var/lib/apt/lists/*
LABEL maintainer "ebusd@ebusd.eu" LABEL maintainer "ebusd@ebusd.eu"
ENV EBUSD_VERSION %EBUSD_VERSION% ARG TARGETARCH
ENV EBUSD_ARCH %EBUSD_ARCH% 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%" 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 \ RUN dpkg -i ebusd.deb \
&& ebusd -V \ && ebusd -V \
&& rm -f ebusd.deb%EXTRA_RM% && rm -f ebusd.deb
EXPOSE 8888 EXPOSE 8888
COPY docker-entrypoint.sh / %EBUSD_COPYENTRY%
ENTRYPOINT ["/docker-entrypoint.sh"] ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["-f", "--scanconfig"] 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 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 [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/). [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. 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 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: The image is able to run on any of the following architectures and the right image will be picked automatically:
* amd64 * amd64
* i386 * i386
* arm32v5
* arm32v7 * arm32v7
* arm64v8 * arm64v8
In addition to the default "latest" tag, a development set of images is available with "devel" tag. This is built Due to changes of docker hub policies, the development set of images with "devel" tag are currently not automatically
automatically with every commit to the git repository. Run the following command to use it: built with every commit to the git repository. Run the following command to use it:
> docker pull john30/ebusd:devel > 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 When using a network device, the "--device" argument to docker can be omitted, but the device information has to be
passed on to ebusd: 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. So when passing further arguments, these two usually need to be added as well.
+52 -17
View File
@@ -1,20 +1,55 @@
#!/bin/bash #!/bin/bash
archs='amd64 i386 arm32v5 arm32v7 arm64v8' if [[ -z "$1" ]]; then
images='stretch buster bullseye' echo "usage: $0 [release|UPLOADHOST]"
UPLOAD_URL='http://'`hostname`'/ebusdreleaseupload.php' 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' UPLOAD_CREDENTIALS='anonymous:build'
for image in $images; do version=`cat ../../VERSION`
dir=$image source='../..'
mkdir -p $dir images='bullseye'
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
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 #!/bin/bash
DEFAULT_IMAGE=debian:bullseye
EBUSD_VERSION=`cat ../../VERSION`
archs='amd64 i386 arm32v5:arm arm32v7:arm arm64v8:aarch64'
function replaceTemplate () { function replaceTemplate () {
prefix= file="Dockerfile${namesuffix}"
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}"
sed \ 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_MAKE%#${make}#g" \
-e "s#%EBUSD_VERSION%#${EBUSD_VERSION}#g" \
-e "s#%EBUSD_VERSION_VARIANT%#${version_variant}#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_UPLOAD_LINES%#${upload_lines}#g" \
-e "s#%EBUSD_COPYDEB%#${copydeb}#g" \
-e "s#%EBUSD_COPYENTRY%#${copyentry}#g" \
Dockerfile.template > "$file" Dockerfile.template > "$file"
echo "updated $file" echo "updated $file"
} }
if [[ -z "$1" ]]; then # devel update
# devel updates version_variant='-devel'
version_variant='-devel' make='./make_debian.sh'
make='./make_debian.sh' upload_lines=''
dir='' copydeb='COPY --from=build /build/ebusd-*_mqtt1.deb ebusd.deb'
upload_line='' copyentry='COPY --from=build /build/contrib/docker/docker-entrypoint.sh /'
namesuffix='' namesuffix=''
for arch in $archs; do replaceTemplate
replaceTemplate
done
fi
# release updates # release update
version_variant='' 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 if [[ -n "$1" ]]; then
# build releases update
make='./make_all.sh' 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' 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='' namesuffix='.build'
else
make='./make_debian.sh'
namesuffix='.release'
fi
for arch in $archs; do
replaceTemplate replaceTemplate
done fi
+287 -302
View File
@@ -10,86 +10,19 @@ paths:
get: get:
summary: Get all messages of all circuits. summary: Get all messages of all circuits.
parameters: parameters:
- name: since - $ref: '#/components/parameters/sinceQuery'
in: query - $ref: '#/components/parameters/pollQuery'
description: limit to messages that have changed since the specified UTC seconds. - $ref: '#/components/parameters/verboseQuery'
allowEmptyValue: false - $ref: '#/components/parameters/indexedQuery'
schema: - $ref: '#/components/parameters/numericQuery'
minimum: 0 - $ref: '#/components/parameters/valuenameQuery'
type: integer - $ref: '#/components/parameters/fullQuery'
- name: poll - $ref: '#/components/parameters/requiredQuery'
in: query - $ref: '#/components/parameters/writeQuery'
description: set the poll priority of matching message(s) to prio. - $ref: '#/components/parameters/rawQuery'
allowEmptyValue: false - $ref: '#/components/parameters/defQuery'
schema: - $ref: '#/components/parameters/userQuery'
minimum: 0 - $ref: '#/components/parameters/secretQuery'
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
responses: responses:
200: 200:
description: Success. description: Success.
@@ -118,92 +51,20 @@ paths:
required: true required: true
schema: schema:
type: string type: string
- name: since - $ref: '#/components/parameters/sinceQuery'
in: query - $ref: '#/components/parameters/pollQuery'
description: limit to messages that have changed since the specified UTC seconds. - $ref: '#/components/parameters/exactQuery'
allowEmptyValue: false - $ref: '#/components/parameters/verboseQuery'
schema: - $ref: '#/components/parameters/indexedQuery'
minimum: 0 - $ref: '#/components/parameters/numericQuery'
type: integer - $ref: '#/components/parameters/valuenameQuery'
- name: poll - $ref: '#/components/parameters/fullQuery'
in: query - $ref: '#/components/parameters/requiredQuery'
description: set the poll priority of matching message(s) to prio. - $ref: '#/components/parameters/writeQuery'
allowEmptyValue: false - $ref: '#/components/parameters/rawQuery'
schema: - $ref: '#/components/parameters/defQuery'
minimum: 0 - $ref: '#/components/parameters/userQuery'
type: integer - $ref: '#/components/parameters/secretQuery'
- 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
responses: responses:
200: 200:
description: Success. description: Success.
@@ -237,92 +98,21 @@ paths:
required: true required: true
schema: schema:
type: string type: string
- name: since - $ref: '#/components/parameters/sinceQuery'
in: query - $ref: '#/components/parameters/pollQuery'
description: limit to messages that have changed since the specified UTC seconds. - $ref: '#/components/parameters/exactQuery'
allowEmptyValue: false - $ref: '#/components/parameters/verboseQuery'
schema: - $ref: '#/components/parameters/indexedQuery'
minimum: 0 - $ref: '#/components/parameters/numericQuery'
type: integer - $ref: '#/components/parameters/valuenameQuery'
- name: poll - $ref: '#/components/parameters/fullQuery'
in: query - $ref: '#/components/parameters/requiredQuery'
description: set the poll priority of matching message(s) to prio. - $ref: '#/components/parameters/writeQuery'
allowEmptyValue: false - $ref: '#/components/parameters/rawQuery'
schema: - $ref: '#/components/parameters/defQuery'
minimum: 0 - $ref: '#/components/parameters/defineQuery'
type: integer - $ref: '#/components/parameters/userQuery'
- name: exact - $ref: '#/components/parameters/secretQuery'
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
responses: responses:
200: 200:
description: Success description: Success
@@ -333,6 +123,66 @@ paths:
500: 500:
description: Circuit or message not found. description: Circuit or message not found.
content: { } 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}: /{file}:
get: get:
summary: Retrieve a particular file. summary: Retrieve a particular file.
@@ -391,36 +241,36 @@ paths:
500: 500:
description: General error. description: General error.
content: { } content: { }
head: # head:
summary: Retrieve headers for a certain file. # summary: Retrieve headers for a certain file.
parameters: # parameters:
- name: file # - name: file
in: path # in: path
description: the file to retrieve. # description: the file to retrieve.
required: true # required: true
schema: # schema:
type: string # type: string
responses: # responses:
200: # 200:
description: Success # description: Success
content: # content:
application/json;charset=utf-8: # application/json;charset=utf-8:
schema: # schema:
$ref: '#/components/schemas/Data' # $ref: '#/components/schemas/Data'
400: # 400:
description: Circuit or message not found. # description: Circuit or message not found.
content: { } # content: { }
components: components:
schemas: schemas:
Global: Global:
required: required:
- lastup - version
- signal
- reconnects
- masters - masters
- messages - messages
- reconnects - lastup
- signal
- version
type: object type: object
properties: properties:
version: version:
@@ -433,6 +283,12 @@ components:
description: the result of update check ("OK" or string describing available description: the result of update check ("OK" or string describing available
updates). updates).
example: revision 1234abd available, 5 newer configuration files available 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: signal:
type: boolean type: boolean
description: whether signal is available. description: whether signal is available.
@@ -447,6 +303,26 @@ components:
type: integer type: integer
description: the maximum symbol rate on the bus seen since start. description: the maximum symbol rate on the bus seen since start.
example: 167 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: qq:
maximum: 255 maximum: 255
minimum: 0 minimum: 0
@@ -487,14 +363,15 @@ components:
example: 8 example: 8
messages: messages:
type: object type: object
description: the messages with the unique key per circuit.
additionalProperties: additionalProperties:
$ref: '#/components/schemas/Message' $ref: '#/components/schemas/Message'
Message: Message:
required: required:
- lastup
- name - name
- passive - passive
- write - write
- lastup
type: object type: object
properties: properties:
name: name:
@@ -506,6 +383,16 @@ components:
write: write:
type: boolean type: boolean
description: true for a write message, false for a read message. 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: lastup:
minimum: 0 minimum: 0
type: integer type: integer
@@ -515,7 +402,7 @@ components:
maximum: 255 maximum: 255
minimum: 0 minimum: 0
type: integer type: integer
description: limited source master address (only with def). description: limited source master address (only with def or data).
example: 49 example: 49
zz: zz:
maximum: 255 maximum: 255
@@ -535,30 +422,34 @@ components:
type: string type: string
description: the message comment (only with verbose). description: the message comment (only with verbose).
master: master:
type: array $ref: '#/components/schemas/Symbols'
description: the last seen master data bytes (only with raw and if available). description: the last seen master data bytes (only with raw and if available).
items:
maximum: 255
minimum: 0
type: integer
slave: slave:
type: array $ref: '#/components/schemas/Symbols'
description: the last seen slave data bytes (only with raw and if available). description: the last seen slave data bytes (only with raw and if available).
items:
maximum: 255
minimum: 0
type: integer
fields: fields:
type: object type: object
additionalProperties: additionalProperties:
$ref: '#/components/schemas/Field' $ref: '#/components/schemas/Field'
description: the decoded fields the message is composed of (only if available). 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: fielddefs:
type: array type: array
description: the field definitions the message is composed of (only with description: the field definitions the message is composed of (only with
def). def).
items: items:
$ref: '#/components/schemas/FieldDef' $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: Field:
type: object type: object
properties: properties:
@@ -566,7 +457,7 @@ components:
type: string type: string
description: the field name. description: the field name.
value: value:
type: object $ref: '#/components/schemas/FieldValue'
description: the field value. description: the field value.
unit: unit:
type: string type: string
@@ -574,13 +465,19 @@ components:
comment: comment:
type: string type: string
description: the field comment (only with verbose). description: the field comment (only with verbose).
FieldValue:
description: the field value.
oneOf:
- type: string
- type: number
nullable: true
FieldDef: FieldDef:
required: required:
- isbits
- length
- name - name
- slave - slave
- type - type
- isbits
- length
type: object type: object
properties: properties:
name: name:
@@ -601,7 +498,8 @@ components:
when isbits is true). when isbits is true).
divisor: divisor:
type: number 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: value:
type: string type: string
description: the constant value (only if applicable). description: the constant value (only if applicable).
@@ -621,6 +519,54 @@ components:
comment: comment:
type: string type: string
description: the field comment. 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: Data:
required: required:
- global - global
@@ -630,6 +576,38 @@ components:
$ref: '#/components/schemas/Global' $ref: '#/components/schemas/Global'
additionalProperties: additionalProperties:
$ref: '#/components/schemas/Circuit' $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: responses:
BadRequest: BadRequest:
description: Invalid request parameters. description: Invalid request parameters.
@@ -676,72 +654,80 @@ components:
name: exact name: exact
in: query in: query
description: exact search for circuit/message name. description: exact search for circuit/message name.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
verboseQuery: verboseQuery:
name: verbose name: verbose
in: query in: query
description: include comments and field units. description: include comments and field units.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
indexedQuery: indexedQuery:
name: indexed name: indexed
in: query in: query
description: always return field indexes instead of names. description: always return field indexes instead of names.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
numericQuery: numericQuery:
name: numeric name: numeric
in: query in: query
description: return numeric values of value list entries. description: return numeric values of value list entries.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
valuenameQuery: valuenameQuery:
name: valuename name: valuename
in: query in: query
description: include value and name for named values. description: include value and name for named values.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
fullQuery: fullQuery:
name: full name: full
in: query in: query
description: include all available attributes. description: include all available attributes.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
requiredQuery: requiredQuery:
name: required name: required
in: query in: query
description: retrieve the data from the bus if not yet cached. description: retrieve the data from the bus if not yet cached.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
writeQuery: writeQuery:
name: write name: write
in: query in: query
description: retrieve write messages in addition to read/poll messages. description: retrieve write messages in addition to read/poll messages.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
rawQuery: rawQuery:
name: raw name: raw
in: query in: query
description: include raw master/slave data. description: include raw master/slave data.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean type: boolean
defQuery: defQuery:
name: def name: def
in: query in: query
description: include message and field definition. description: include message and field definition.
allowEmptyValue: false allowEmptyValue: true
schema: schema:
type: boolean 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: userQuery:
name: user name: user
in: query in: query
@@ -756,4 +742,3 @@ components:
allowEmptyValue: false allowEmptyValue: false
schema: schema:
type: string type: string
+1 -1
View File
@@ -5,4 +5,4 @@ echo "ebusd=${version},${revision}" > versions.txt
echo "ebusd=${version},${revision}" > oldversions.txt echo "ebusd=${version},${revision}" > oldversions.txt
files=`find config/ -type f -or -type l` 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 ../../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 # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
pwd
ls -la
keepbuilddir= keepbuilddir=
if [ "x$1" = "x--keepbuilddir" ]; then if [ "x$1" = "x--keepbuilddir" ]; then
keepbuilddir=1 keepbuilddir=1
@@ -80,16 +78,21 @@ else
fi fi
fi fi
echo if [ -n "$RUNTEST" ]; then
echo "*************" echo
echo " test" echo "*************"
echo "*************" echo " test"
echo echo "*************"
testdie() { echo
echo "test failed" testdie() {
exit 1 echo "test failed"
} exit 1
(cd src/lib/ebus/test && make test_data >/dev/null && ./test_data) || testdie }
($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
echo "*************" echo "*************"
@@ -97,7 +100,6 @@ echo " pack"
echo "*************" echo "*************"
echo echo
mkdir -p $RELEASE/DEBIAN $RELEASE/etc/default $RELEASE/etc/logrotate.d || exit 1 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 mkdir -p $RELEASE/lib/systemd/system || exit 1
cp contrib/debian/systemd/ebusd.service $RELEASE/lib/systemd/system/ebusd.service || exit 1 cp contrib/debian/systemd/ebusd.service $RELEASE/lib/systemd/system/ebusd.service || exit 1
mkdir -p $RELEASE/etc/init.d || exit 1 mkdir -p $RELEASE/etc/init.d || exit 1
@@ -114,13 +116,13 @@ Architecture: $ARCH
Maintainer: John Baier <ebusd@ebusd.eu> Maintainer: John Baier <ebusd@ebusd.eu>
Homepage: https://github.com/john30/ebusd Homepage: https://github.com/john30/ebusd
Bugs: https://github.com/john30/ebusd/issues 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. Description: eBUS daemon.
ebusd is a daemon for handling communication with eBUS devices connected to a ebusd is a daemon for handling communication with eBUS devices connected to a
2-wire bus system. 2-wire bus system.
EOF EOF
cat <<EOF > $RELEASE/DEBIAN/dirs cat <<EOF > $RELEASE/DEBIAN/dirs
/etc/ebusd
/etc/default /etc/default
/etc/init.d /etc/init.d
/etc/logrotate.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; return !first;
} }
bool GrabbedMessage::dump(bool unknown, MessageMap* messages, bool first, bool decode, ostringstream* output, bool GrabbedMessage::dump(bool unknown, MessageMap* messages, bool first, OutputFormat outputFormat,
bool isDirectMode) const { ostringstream* output, bool isDirectMode) const {
Message* message = messages->find(m_lastMaster); Message* message = messages->find(m_lastMaster);
if (unknown && message) { if (unknown && message) {
return false; return false;
} }
if (!first) { if (!first) {
*output << endl; if (outputFormat & OF_JSON) {
*output << ",";
} else {
*output << endl;
}
} }
symbol_t dstAddress = m_lastMaster[1]; symbol_t dstAddress = m_lastMaster[1];
*output << m_lastMaster.getStr(); if (outputFormat & OF_JSON) {
if (dstAddress != BROADCAST && !isMaster(dstAddress)) { *output << "\n{";
*output << (isDirectMode ? " " : " / ") << m_lastSlave.getStr(); if (m_lastMaster.dumpJson(false, output)) {
} *output << ", ";
if (!isDirectMode) { if (dstAddress != BROADCAST && !isMaster(dstAddress) && m_lastSlave.dumpJson(false, output)) {
*output << " = " << m_count; *output << ", ";
}
}
*output << "\"count\": " << static_cast<unsigned>(m_count);
*output << ", \"lastup\": " << setw(0) << dec << m_lastTime;
if (message) { 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) { if (!(outputFormat & OF_DEFINITION) || (outputFormat & OF_JSON)) {
DataTypeList *types = DataTypeList::getInstance(); return true;
if (!types) { }
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 maxLength = baseType->getBitCount()/8;
size_t remain = master ? m_lastMaster.getDataSize() : m_lastSlave.getDataSize(); bool firstOnly = maxLength >= 8;
if (remain == 0) { if (maxLength > remain) {
return true; maxLength = remain;
} }
for (const auto& it : *types) { if (baseType->isAdjustableLength()) {
const DataType* baseType = it.second; for (size_t length = maxLength; length >= 1; length--) {
if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored()) { // skip bit and ignored types const DataType* type = types->get(baseType->getId(), length);
continue; bool decoded;
}
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 (master) { if (master) {
decodeType(baseType, m_lastMaster, maxLength, remain-maxLength, false, output); decoded = decodeType(type, m_lastMaster, length, remain-length, firstOnly, output);
} else { } 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()); } while (isRunning());
} }
#ifndef FALLTHROUGH
#if defined(__GNUC__) && __GNUC__ >= 7
#define FALLTHROUGH [[fallthrough]];
#else
#define FALLTHROUGH
#endif
#endif
result_t BusHandler::handleSymbol() { result_t BusHandler::handleSymbol() {
unsigned int timeout = SYN_TIMEOUT; unsigned int timeout = SYN_TIMEOUT;
symbol_t sendSymbol = ESC; symbol_t sendSymbol = ESC;
@@ -438,6 +468,7 @@ result_t BusHandler::handleSymbol() {
case bs_skip: case bs_skip:
timeout = SYN_TIMEOUT; timeout = SYN_TIMEOUT;
FALLTHROUGH
case bs_ready: case bs_ready:
if (m_currentRequest != nullptr) { if (m_currentRequest != nullptr) {
setState(bs_ready, RESULT_ERR_TIMEOUT); // just to be sure an old BusRequest is cleaned up 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; 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 { time_t since, time_t until) const {
if (!m_grabMessages) { if (!m_grabMessages) {
if (!isDirectMode) { if (!isDirectMode && !(outputFormat & OF_JSON)) {
*output << "grab disabled"; *output << "grab disabled";
} }
return; return;
@@ -1615,7 +1646,7 @@ void BusHandler::formatGrabResult(bool unknown, bool decode, ostringstream* outp
|| (until > 0 && it.second.getLastTime() >= until)) { || (until > 0 && it.second.getLastTime() >= until)) {
continue; 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; first = false;
} }
} }
+4 -4
View File
@@ -334,12 +334,12 @@ class GrabbedMessage {
* @param unknown whether to dump only if this message is unknown. * @param unknown whether to dump only if this message is unknown.
* @param messages the @a MessageMap instance for resolving known @a Message instances. * @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 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 output the @a ostringstream to format the messages to.
* @param isDirectMode true for direct mode, false for grab command. * @param isDirectMode true for direct mode, false for grab command.
* @return whether the message was added to the output. * @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; bool isDirectMode = false) const;
@@ -538,13 +538,13 @@ class BusHandler : public WaitThread {
/** /**
* Format the grabbed messages to the @a ostringstream. * Format the grabbed messages to the @a ostringstream.
* @param unknown whether to dump only unknown messages. * @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 output the @a ostringstream to format the messages to.
* @param isDirectMode true for direct mode, false for grab command. * @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 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. * @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; 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); s_mainLoop = new MainLoop(opt, device, s_messageMap);
if (opt.injectMessages) { if (opt.injectMessages) {
BusHandler* busHandler = s_mainLoop->getBusHandler(); BusHandler* busHandler = s_mainLoop->getBusHandler();
MasterSymbolString master;
SlaveSymbolString slave;
while (arg_index < argc) { while (arg_index < argc) {
// add each passed message // add each passed message
MasterSymbolString master;
SlaveSymbolString slave;
if (!parseMessage(argv[arg_index++], false, &master, &slave)) { if (!parseMessage(argv[arg_index++], false, &master, &slave)) {
continue; continue;
} }
+148 -20
View File
@@ -434,14 +434,14 @@ void MainLoop::run() {
} }
if (settings.listenWithUnknown || settings.listenOnlyUnknown) { if (settings.listenWithUnknown || settings.listenOnlyUnknown) {
if (m_busHandler->isGrabEnabled()) { if (m_busHandler->isGrabEnabled()) {
m_busHandler->formatGrabResult(true, false, &ostream, true, since, now); m_busHandler->formatGrabResult(true, OF_NONE, &ostream, true, since, now);
} else { } else {
m_busHandler->enableGrab(true); // needed for listening to all messages m_busHandler->enableGrab(true); // needed for listening to all messages
} }
} }
} else if (settings.mode == cm_direct) { } else if (settings.mode == cm_direct) {
if (m_busHandler->isGrabEnabled()) { 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 // send result to client
@@ -607,7 +607,7 @@ result_t MainLoop::decodeMessage(const string &data, bool isHttp, bool* connecte
if (cmd == "G" || cmd == "GRAB") { if (cmd == "G" || cmd == "GRAB") {
return executeGrab(args, ostream); return executeGrab(args, ostream);
} }
if (cmd == "DEFINE") { if (cmd == "DEF" || cmd == "DEFINE") {
if (m_newlyDefinedMessages) { if (m_newlyDefinedMessages) {
return executeDefine(args, ostream); return executeDefine(args, ostream);
} }
@@ -921,8 +921,6 @@ result_t MainLoop::executeRead(const vector<string>& args, const string& levels,
Message* message; Message* message;
result_t ret; result_t ret;
if (newDefinition) { if (newDefinition) {
time_t now;
time(&now);
string errorDescription; string errorDescription;
istringstream defstr("#\n" + args[argPos]); // ensure first line is not used for determining col names istringstream defstr("#\n" + args[argPos]); // ensure first line is not used for determining col names
m_newlyDefinedMessages->clear(); 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) { result_t MainLoop::executeHex(const vector<string>& args, ostringstream* ostream) {
size_t argPos = 1; size_t argPos = 1;
result_t ret = parseHexAndSend(args, argPos, false, ostream); result_t ret = parseHexAndSend(args, argPos, false, ostream);
if (argPos == args.size()) { if (argPos != 0 && argPos == args.size()) {
return ret; return ret;
} }
*ostream << "usage: hex [-s QQ] ZZPBSBNN[DD]*\n" *ostream << "usage: hex [-s QQ] ZZPBSBNN[DD]*\n"
@@ -1641,7 +1639,7 @@ result_t MainLoop::executeGrab(const vector<string>& args, ostringstream* ostrea
} }
} }
if (!invalid) { if (!invalid) {
m_busHandler->formatGrabResult(onlyUnknown, decode, ostream); m_busHandler->formatGrabResult(onlyUnknown, decode ? OF_DEFINITION : OF_NONE, ostream);
return RESULT_OK; return RESULT_OK;
} }
} }
@@ -1677,7 +1675,7 @@ result_t MainLoop::executeDefine(const vector<string>& args, ostringstream* ostr
time(&now); time(&now);
string errorDescription; string errorDescription;
istringstream defstr("#\n" + args[argPos]); // ensure first line is not used for determining col names 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) { result_t MainLoop::executeInfo(const vector<string>& args, const string& user, ostringstream* ostream) {
if (args.size() == 0) { bool verbose = args.size() == 2 && args[1] == "verbose";
*ostream << "usage: info\n" if (args.size() != 1 && !verbose) {
" Report information about the daemon, the configuration, and seen devices."; *ostream << "usage: info [verbose]\n"
" Report information about the daemon, configuration, seen participants, and the device.";
return RESULT_OK; return RESULT_OK;
} }
*ostream << "version: " << PACKAGE_STRING "." REVISION "\n"; *ostream << "version: " << PACKAGE_STRING "." REVISION "\n";
if (!m_updateCheck.empty()) { if (!m_updateCheck.empty()) {
*ostream << "update check: " << m_updateCheck << "\n"; *ostream << "update check: " << m_updateCheck << "\n";
} }
string info = m_device->getEnhancedInfos(); *ostream << "device: " << m_device->getName();
if (!info.empty()) { if (m_device->isEnhancedProto()) {
*ostream << "device: " << info << "\n"; *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()) { if (!user.empty()) {
*ostream << "user: " << user << "\n"; *ostream << "user: " << user << "\n";
} }
@@ -1962,8 +1971,8 @@ result_t MainLoop::executeHelp(ostringstream* ostream) {
*ostream << "usage:\n" *ostream << "usage:\n"
" read|r Read value(s): read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-c CIRCUIT] [-p PRIO] [-v|-V] [-n|-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" " [-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)" " Read by new defintion: read [-f] [-m SECONDS] [-s QQ] [-d ZZ] [-v|-V] [-n|-N]"
" [-i VALUE[;VALUE]*] -def DEFINITION\n" " [-i VALUE[;VALUE]*] -def DEFINITION (if enabled)\n"
" Read hex message: read [-f] [-m SECONDS] [-s QQ] [-c CIRCUIT] -h ZZPBSBNN[DD]*\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|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" " 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" " listen|l Listen for updates: listen [-v|-V] [-n|-N] [-u|-U] [stop]\n"
" direct Enter direct mode\n" " direct Enter direct mode\n"
" state|s Report bus state\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" " grab|g Grab messages: grab [stop]\n"
" Report the messages: grab result [all]\n" " Report the messages: grab result [all]\n"
" define Define new message: define [-r] DEFINITION\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) { 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; time_t maxAge = -1;
size_t argPos = 1; size_t argPos = 1;
string uri = args[argPos++]; 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); circuit = uri.substr(6, pos - 6);
name = uri.substr(pos + 1); 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; time_t since = 0;
size_t pollPriority = 0; size_t pollPriority = 0;
bool exact = false; bool exact = false;
@@ -2072,6 +2082,18 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
raw = parseBoolQuery(value); raw = parseBoolQuery(value);
} else if (qname == "def") { } else if (qname == "def") {
withDefinition = parseBoolQuery(value); 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") { } else if (qname == "user") {
user = value; user = value;
} else if (qname == "secret") { } else if (qname == "secret") {
@@ -2091,6 +2113,11 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
time_t now; time_t now;
time(&now); time(&now);
time_t maxLastUp = 0; 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) { if (ret == RESULT_OK) {
bool first = true; bool first = true;
verbosity |= OF_JSON | (full ? OF_ALL_ATTRS : OF_NONE) | (withDefinition ? OF_DEFINITION : OF_NONE); 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); return formatHttpResult(ret, type, ostream);
} // request for "/data..." } // 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) { if (uri.length() < 1 || uri[0] != '/' || uri.find("//") != string::npos || uri.find("..") != string::npos) {
ret = RESULT_ERR_INVALID_ARG; ret = RESULT_ERR_INVALID_ARG;
} else { } else {
+8 -2
View File
@@ -46,6 +46,7 @@ using std::dec;
#define O_KEYF (O_CERT+1) #define O_KEYF (O_CERT+1)
#define O_KEPA (O_KEYF+1) #define O_KEPA (O_KEYF+1)
#define O_INSE (O_KEPA+1) #define O_INSE (O_KEPA+1)
#define O_VERB (O_INSE+1)
/** the definition of the MQTT arguments. */ /** the definition of the MQTT arguments. */
static const struct argp_option g_mqtt_argp_options[] = { 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 }, "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 }, {"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 }, {"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) #if (LIBMOSQUITTO_VERSION_NUMBER >= 1003001)
{"mqttlog", O_LOGL, nullptr, 0, "Log library events", 0 }, {"mqttlog", O_LOGL, nullptr, 0, "Log library events", 0 },
#endif #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 }, {"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 }, {"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 }, {"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 #endif
{nullptr, 0, nullptr, 0, nullptr, 0 }, {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; g_publishFormat |= OF_JSON|OF_NAMES;
break; break;
case O_VERB: // --mqttverbose
g_publishFormat |= OF_NAMES|OF_UNITS|OF_COMMENTS|OF_ALL_ATTRS;
break;
#if (LIBMOSQUITTO_VERSION_NUMBER >= 1003001) #if (LIBMOSQUITTO_VERSION_NUMBER >= 1003001)
case O_LOGL: case O_LOGL:
g_logFromLib = true; g_logFromLib = true;
@@ -909,7 +915,7 @@ void MqttHandler::publishMessage(const Message* message, ostringstream* updates,
publishTopic(getTopic(message), updates->str()); publishTopic(getTopic(message), updates->str());
return; return;
} }
if (json) { if (json && !(outputFormat & OF_ALL_ATTRS)) {
outputFormat |= OF_SHORT; outputFormat |= OF_SHORT;
} }
for (size_t index = 0; index < message->getFieldCount(); index++) { 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 { bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
if (outputFormat & OF_JSON) { if (outputFormat & OF_JSON) {
*output << "\"type\": \"" << m_id << "\", \"isbits\": " *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) { if (isAdjustableLength() && length == REMAIN_LEN) {
*output << "-1"; *output << "-1";
} else { } else {
@@ -54,10 +59,11 @@ bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor
} else { } else {
*output << m_id; *output << m_id;
if (isAdjustableLength()) { if (isAdjustableLength()) {
*output << LENGTH_SEPARATOR;
if (length == REMAIN_LEN) { if (length == REMAIN_LEN) {
*output << ":*"; *output << "*";
} else { } else {
*output << ":" << static_cast<unsigned>(length); *output << static_cast<unsigned>(length);
} }
} }
if (appendDivisor) { 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 { result_t StringDataType::readRawValue(size_t, size_t, const SymbolString&, unsigned int*) const {
return RESULT_EMPTY; 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 { result_t DateTimeDataType::readRawValue(size_t, size_t, const SymbolString&, unsigned int*) const {
return RESULT_EMPTY; return RESULT_EMPTY;
} }
@@ -572,25 +594,32 @@ bool NumberDataType::dump(OutputFormat outputFormat, size_t length, bool appendD
} else { } else {
DataType::dump(outputFormat, length, appendDivisor, output); DataType::dump(outputFormat, length, appendDivisor, output);
} }
if ((outputFormat & OF_JSON) && (outputFormat & OF_ALL_ATTRS)) {
*output << ", \"result\": \"number\"";
}
if (!appendDivisor) { if (!appendDivisor) {
return false; return false;
} }
bool ret = false;
if (m_baseType) { if (m_baseType) {
if (m_baseType->m_divisor != m_divisor) { if (m_baseType->m_divisor != m_divisor) {
if (outputFormat & OF_JSON) { if (outputFormat & OF_JSON) {
*output << ", \"divisor\": "; *output << ", \"divisor\": ";
} }
*output << (m_divisor / m_baseType->m_divisor); *output << (m_divisor / m_baseType->m_divisor);
return true; ret = true;
} }
} else if (m_divisor != 1) { } else if (m_divisor != 1) {
if (outputFormat & OF_JSON) { if (outputFormat & OF_JSON) {
*output << ", \"divisor\": "; *output << ", \"divisor\": ";
} }
*output << m_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 { 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, // 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) // WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
add(new DateTimeDataType("BDA", 32, BCD, 0xff, true, false, 0)); 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) // 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, // 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) // WZ is zero-based weekday Mon=0x00 - Sun=0x06, replacement 0xff)
add(new DateTimeDataType("BDZ", 32, BCD|SPE, 0xff, true, false, 0)); 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, // 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) // WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
add(new DateTimeDataType("HDA", 32, 0, 0xff, true, false, 0)); 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) // 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) // 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)); 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) // 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("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("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", 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:1", 8, BCD|DUP, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99
add(new NumberDataType("BCD", 24, BCD, 0xffffff, 0, 999999, 1)); // unsigned decimal in BCD, 0 - 999999 add(new NumberDataType("BCD:2", 16, BCD, 0xffff, 0, 9999, 1)); // unsigned decimal in BCD, 0 - 9999
add(new NumberDataType("BCD", 32, BCD, 0xffffffff, 0, 99999999, 1)); // unsigned decimal in BCD, 0 - 99999999 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", 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:4", 32, HCD|BCD|REQ|DUP, 0, 0, 99999999, 1)); // unsigned decimal in HCD, 0 - 99999999
add(new NumberDataType("HCD", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // unsigned decimal in HCD, 0 - 9999 add(new NumberDataType("HCD:1", 8, HCD|BCD|REQ, 0, 0, 99, 1)); // unsigned decimal in HCD, 0 - 99
add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999 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("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 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) // 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("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("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("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() { DataTypeList* DataTypeList::getInstance() {
return &s_instance; 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() { void DataTypeList::clear() {
for (auto& it : m_cleanupTypes) { for (auto& it : m_cleanupTypes) {
delete it; delete it;
} }
m_cleanupTypes.clear(); m_cleanupTypes.clear();
m_typesByIdLength.clear();
m_typesById.clear(); m_typesById.clear();
} }
result_t DataTypeList::add(const DataType* dataType) { result_t DataTypeList::add(const DataType* dataType) {
if (!dataType->isAdjustableLength()) { if (m_typesById.find(dataType->getId()) != m_typesById.end()) {
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()) {
return RESULT_ERR_DUPLICATE_NAME; // duplicate key return RESULT_ERR_DUPLICATE_NAME; // duplicate key
} }
m_typesById[dataType->getId()] = dataType; m_typesById[dataType->getId()] = dataType;
@@ -1117,8 +1162,8 @@ const DataType* DataTypeList::get(const string& id, size_t length) const {
if (length > 0) { if (length > 0) {
ostringstream str; ostringstream str;
str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length); str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length);
auto it = m_typesByIdLength.find(str.str()); auto it = m_typesById.find(str.str());
if (it != m_typesByIdLength.end()) { if (it != m_typesById.end()) {
return it->second; return it->second;
} }
} }
+20 -10
View File
@@ -178,9 +178,8 @@ enum PartType {
/** bit flag for @a DataType: special marker for certain types. */ /** bit flag for @a DataType: special marker for certain types. */
#define SPE 0x800 #define SPE 0x800
/** bit flag for @a DataType: marker for a constant value. */ /** bit flag for @a DataType: stored duplicate for backwards compatibility, not to be traversed in lists any more. */
#define CON 0x1000 #define DUP 0x1000
/** /**
* Base class for all kinds of data types. * Base class for all kinds of data types.
@@ -326,6 +325,9 @@ class StringDataType : public DataType {
*/ */
virtual ~StringDataType() {} virtual ~StringDataType() {}
// @copydoc
bool dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const override;
// @copydoc // @copydoc
result_t readRawValue(size_t offset, size_t length, const SymbolString& input, result_t readRawValue(size_t offset, size_t length, const SymbolString& input,
unsigned int* value) const override; unsigned int* value) const override;
@@ -370,6 +372,9 @@ class DateTimeDataType : public DataType {
*/ */
virtual ~DateTimeDataType() {} virtual ~DateTimeDataType() {}
// @copydoc
bool dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const override;
/** /**
* @return true if date part is present. * @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, NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
unsigned int minValue, unsigned int maxValue, int divisor, unsigned int minValue, unsigned int maxValue, int divisor,
const NumberDataType* baseType = nullptr) 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) {} 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, NumberDataType(const string& id, size_t bitCount, uint16_t flags, unsigned int replacement,
int16_t firstBit, int divisor, const NumberDataType* baseType = nullptr) 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) {} m_precision(0), m_firstBit(firstBit), m_baseType(baseType) {}
/** /**
@@ -570,6 +575,14 @@ class DataTypeList {
*/ */
static DataTypeList* getInstance(); 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. * Removes all @a DataType instances.
*/ */
@@ -611,12 +624,9 @@ class DataTypeList {
map<string, const DataType*>::const_iterator end() const { return m_typesById.end(); } map<string, const DataType*>::const_iterator end() const { return m_typesById.end(); }
private: private:
/** the known @a DataType instances by ID only. */ /** the known @a DataType instances by ID (e.g. "ID:BITS" or just "ID").
map<string, const DataType*> m_typesById;
/** the known @a DataType instances by ID and length (i.e. "ID:BITS").
* Note: adjustable length types are stored by ID only. */ * 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. */ /** the @a DataType instances to cleanup. */
list<const DataType*> m_cleanupTypes; 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); 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, void Message::decodeJson(bool leadingSeparator, bool appendDirectionCondition, bool withData, bool addRaw,
OutputFormat outputFormat, ostringstream* output) const { OutputFormat outputFormat, ostringstream* output) const {
outputFormat |= OF_JSON; outputFormat |= OF_JSON;
@@ -1005,8 +991,8 @@ void Message::decodeJson(bool leadingSeparator, bool appendDirectionCondition, b
appendAttributes(outputFormat, output); appendAttributes(outputFormat, output);
if (hasData) { if (hasData) {
if (addRaw) { if (addRaw) {
addData(m_lastMasterData, output); m_lastMasterData.dumpJson(true, output);
addData(m_lastSlaveData, output); m_lastSlaveData.dumpJson(true, output);
*output << dec; *output << dec;
} }
size_t pos = (size_t)output->tellp(); size_t pos = (size_t)output->tellp();
@@ -1884,27 +1870,27 @@ void MessageMap::remove(Message* message) {
const auto keyIt = m_messagesByKey.find(key); const auto keyIt = m_messagesByKey.find(key);
bool deleted = false; bool deleted = false;
if (keyIt != m_messagesByKey.end()) { if (keyIt != m_messagesByKey.end()) {
vector<Message*> messages = keyIt->second; vector<Message*>* messages = &keyIt->second;
for (auto it = messages.begin(); it != messages.end(); ) { for (auto it = messages->begin(); it != messages->end(); ) {
Message* other = *it; Message* other = *it;
if (other == message) { if (other == message) {
if (!deleted) { if (!deleted) {
deleted = true; deleted = true;
delete(other); delete(other);
} }
messages.erase(it); it = messages->erase(it);
} else { } else {
++it; ++it;
} }
} }
if (messages.empty()) { if (messages->empty()) {
m_messagesByKey.erase(keyIt); m_messagesByKey.erase(keyIt);
} }
} }
bool storedByName = false; bool storedByName = false;
for (auto nameIt = m_messagesByName.begin(); nameIt != m_messagesByName.end(); ) { for (auto nameIt = m_messagesByName.begin(); nameIt != m_messagesByName.end(); ) {
vector<Message*> messages = nameIt->second; vector<Message*>* messages = &nameIt->second;
for (auto it = messages.begin(); it != messages.end(); ) { for (auto it = messages->begin(); it != messages->end(); ) {
Message* other = *it; Message* other = *it;
if (other == message) { if (other == message) {
storedByName = true; storedByName = true;
@@ -1912,13 +1898,13 @@ void MessageMap::remove(Message* message) {
deleted = true; deleted = true;
delete(other); delete(other);
} }
messages.erase(it); it = messages->erase(it);
} else { } else {
++it; ++it;
} }
} }
if (messages.empty()) { if (messages->empty()) {
m_messagesByName.erase(nameIt); nameIt = m_messagesByName.erase(nameIt);
} else { } else {
++nameIt; ++nameIt;
} }
+5 -1
View File
@@ -122,7 +122,11 @@ class Message : public AttributedItem {
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Message() { if (m_deleteData) { delete m_data; } } virtual ~Message() {
if (m_deleteData) {
delete m_data;
}
}
/** /**
* Calculate the key for the ID. * Calculate the key for the ID.
+19
View File
@@ -28,6 +28,7 @@ namespace ebusd {
using std::ostringstream; using std::ostringstream;
using std::nouppercase; using std::nouppercase;
using std::setw; using std::setw;
using std::dec;
using std::hex; using std::hex;
using std::setfill; using std::setfill;
@@ -157,6 +158,24 @@ const string SymbolString::getStr(size_t skipFirstSymbols) const {
return sstr.str(); 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 SymbolString::calcCrc() const {
symbol_t crc = 0; symbol_t crc = 0;
for (size_t i = 0; i < m_data.size(); i++) { for (size_t i = 0; i < m_data.size(); i++) {
+9
View File
@@ -67,6 +67,7 @@ namespace ebusd {
using std::string; using std::string;
using std::vector; using std::vector;
using std::ostringstream;
/** the base type for symbols sent to/from the eBUS. */ /** the base type for symbols sent to/from the eBUS. */
typedef unsigned char symbol_t; typedef unsigned char symbol_t;
@@ -158,6 +159,14 @@ class SymbolString {
*/ */
const string getStr(size_t skipFirstSymbols = 0) const; 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. * Return a reference to the symbol at the specified index.
* @param index the index of the symbol to return. * @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;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" }, {"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,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,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,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,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,,,,,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: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,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,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,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" }, {"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: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,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,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,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,,,,,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: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,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,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,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" }, {"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;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", "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" }, {"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(ebusctl_SOURCES ebusctl.cpp)
set(ebusfeed_SOURCES ebusfeed.cpp)
set(ebuspicloader_SOURCES ebuspicloader.cpp intelhex/intelhexclass.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/ebus)
include_directories(../lib/utils) include_directories(../lib/utils)
include_directories(intelhex) include_directories(intelhex)
add_executable(ebusctl ${ebusctl_SOURCES}) add_executable(ebusctl ${ebusctl_SOURCES})
add_executable(ebusfeed ${ebusfeed_SOURCES})
add_executable(ebuspicloader ${ebuspicloader_SOURCES}) add_executable(ebuspicloader ${ebuspicloader_SOURCES})
target_link_libraries(ebusctl utils ebus ${LIB_ARGP} ${ebusctl_LIBS}) 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}) target_link_libraries(ebuspicloader ${LIB_ARGP})
install(TARGETS ebusctl ebuspicloader EXPORT ebusd DESTINATION usr/bin) 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) -isystem$(top_srcdir)
bin_PROGRAMS = ebusctl \ bin_PROGRAMS = ebusctl \
ebusfeed \
ebuspicloader ebuspicloader
ebusctl_SOURCES = ebusctl.cpp ebusctl_SOURCES = ebusctl.cpp
ebusctl_LDADD = ../lib/utils/libutils.a 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 ebuspicloader_SOURCES = ebuspicloader.cpp intelhex/intelhexclass.cpp
if CONTRIB
ebusfeed_LDADD += ../lib/ebus/contrib/libebuscontrib.a
endif
distclean-local: distclean-local:
-rm -f Makefile.in -rm -f Makefile.in
-rm -rf .libs -rm -rf .libs
-9
View File
@@ -63,15 +63,6 @@ EOF
./src/ebusd/ebusd -c contrib/etc/ebusd --checkconfig >/dev/null ./src/ebusd/ebusd -c contrib/etc/ebusd --checkconfig >/dev/null
rm -f contrib/etc/ebusd/bad.csv rm -f contrib/etc/ebusd/bad.csv
echo > dump 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 testserver -p 100000 >/dev/null 2>/dev/null
./src/tools/ebusctl -s "" >/dev/null 2>/dev/null ./src/tools/ebusctl -s "" >/dev/null 2>/dev/null
./src/tools/ebusctl -p "" >/dev/null 2>/dev/null ./src/tools/ebusctl -p "" >/dev/null 2>/dev/null