Giter VIP home page Giter VIP logo

brickd's Introduction

Brick Daemon

This repository contains the source code of the Brick Daemon. Prebuild installers/packages for various platforms are provided here:

https://www.tinkerforge.com/en/doc/Downloads.html

Supported Platforms

  • Linux with libusb 1.0.20 or newer
  • Windows Vista or newer
  • macOS 10.9 (Mavericks) or newer

Using the Tinkerforge APT Repository

We provide prebuild .deb packages for Debian based Linux distributions.

Follow the steps in the readme for your distribution to set up the repository:

  • Debian:

    https://download.tinkerforge.com/apt/debian/readme.txt
    
  • Ubuntu:

    https://download.tinkerforge.com/apt/ubuntu/readme.txt
    
  • Raspberry Pi OS (Raspbian):

    https://download.tinkerforge.com/apt/raspbian/readme.txt
    

Install Brick Daemon package:

sudo apt install brickd

Compiling the Source Code (instead of using prebuild installer/package)

Instead of using the prebuild installer/package, Brick Daemon can also be compiled from source code for various platforms.

Brick Daemon uses the Tinkerforge daemonlib:

https://github.com/Tinkerforge/daemonlib

It has to be cloned or symlinked to the src/daemonlib/ directory before the source code can be compiled. Make sure that you're using matching versions of the brickd and daemonlib source code. If you're using the current git version of brickd then you also need the current git version of daemonlib. If you're using a specific release of brickd (e.g. tagged v2.3.0) then you also need the matching release of daemonlib (e.g. tagged brickd-2.3.0).

Brick Daemon also depends on the following libraries:

  • libusb-1.0 (mandatory)
  • pm-utils (optional for suspend/resume handling, Linux without systemd only)
  • libgpiod (mandatory, Linux only)

On Debian based Linux distributions try:

sudo apt-get install build-essential pkg-config libusb-1.0-0-dev pm-utils libgpiod-dev

On Fedora Linux try:

sudo yum groupinstall "Development Tools"
sudo yum install libusb1-devel pm-utils-devel

For Windows and macOS a suitable pre-compiled libusb-1.0 binary is part of this repository.

Linux

A Makefile is provided to compile the source code using GCC and install the result. The Makefile will autodetect the availability of pm-utils:

cd src/brickd
make
sudo make install

Run the following commands to register brickd for autostart on Debian based Linux distribution and start it:

sudo systemctl enable brickd
sudo systemctl enable brickd-resume
sudo systemctl start brickd

On Debian based Linux distribution without systemd run the following commands instead:

sudo update-rc.d brickd defaults
sudo invoke-rc.d brickd start

Windows

A batch file compile.bat is provided to compile the source code using the Visual Studio (MSVC) compiler. Open a MSVC command prompt:

cd src\brickd
compile.bat

The brickd.exe binary is created in src\dist\.

For the MinGW compiler there is a Makefile to compile the source code:

cd src\brickd
mingw32-make

The brickd.exe binary is created in src\dist\.

Alternatively, there is a Visual Studio 2019 project file to compile the source code:

src\build_data\windows\msvc\brickd.sln

Windows 10 IoT Core (Universal Windows Platform)

There is a Visual Studio 2019 project file to compile the source code:

src\build_data\windows\msvc_uwp\brickd_uwp.sln

The "Windows IoT Core Project Templates" extension has to be installed first. The project file builds a UWP app that has been successfully tested on a Raspberry Pi running Windows 10 IoT Core with Bricks connected to USB. But there is a currently unsolved problem with USB device detection:

https://www.tinkerforge.com/en/blog/2016/7/12/brick-daemon-beta-fuer-windows-10-iot-core-teil-1-2/

TL;DR: There seems to be a bug in Windows 10 IoT Core that stops Bricks from being properly detected as USB devices. Because of this bug Brick Daemon cannot access them out-of-the-box.

You have to run the following command on your Raspberry Pi, while replacing the placeholder <UID> in the command with the UID of the Brick you want to connect:

reg add "HKLM\System\CurrentControlSet\Enum\USB\VID_16D0&PID_063D\<UID>\Device Parameters" /v DeviceInterfaceGUIDs /t REG_MULTI_SZ /d "{870013DD-FB1D-4BD7-A96C-1F0B7D31AF41}"

This has to be done for every Brick that you want to connect to the Raspberry Pi.

There is also experimental support for the HAT (Zero) Brick for the Raspberry Pi. It's experimental because Windows 10 IoT Core doesn't provide HAT detection for the Raspberry Pi and it also doesn't allow to access the I2C interface used for HAT detection on Raspbian to solve this in Brick Daemon itself.

This means that Brick Daemon cannot detect if a HAT is connected or which kind of HAT is connected. Therefore, HAT (Zero) Brick support cannot be enabled by default and one of the preprocessor define BRICKD_WITH_UWP_HAT_BRICK or BRICKD_WITH_UWP_HAT_ZERO_BRICK has to be defined in the Visual Studio 2019 project file to enable HAT (Zero) Brick support.

macOS

A Makefile is provided to compile the source code using GCC:

cd src/brickd
make

The brickd binary is created in src/brickd/.

Building Packages

Packages can be build for multiple platforms.

Linux, Windows and macOS

The Python script src/build_pkg.py can build a Debian package for Linux, a NSIS based setup.exe for Windows and a Disk Image for macOS. Run:

python build_pkg.py

On Windows this has to be executed from a MSVC or WDK command prompt because it invokes the platform specific commands to compile the source code.

The installer/package is created in src.

OpenWrt

There is also a Makefile to build an OpenWrt package. To include the package into your OpenWrt build simply link or copy the src/build_data/openwrt/ folder to the package directory of your OpenWrt build tree, select the brickd2 package in the menuconfig and build.

USB Hotplug Detection

Brick Daemon can autodetect USB hotplug. Different systems are used for this:

  • libusb hotplug callback on non-Windows systems
  • Win32 device notification on Windows systems

On Linux brickd will also check for added or removed Bricks if the SIGUSR1 signal is received. This is used on OpenWrt where the hotplug2 daemon is told to tell brickd about USB hotplug this way, instead of using libudev on OpenWrt.

brickd's People

Contributors

andreas-schwab avatar batti avatar bjoern-r avatar borg42 avatar iia avatar lnussel avatar niklaskroeger avatar photron avatar rtrbt avatar tewdreyer avatar tyll avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

brickd's Issues

Windows Uninstaller may delete important user files

Hi,

my anti virus sandbox identified your uninstaller as potential malware, because it deleted all user files in the sandbox. After manual investigation it turns out there is an issue with your uninstaller. Your script runs (https://github.com/Tinkerforge/brickd/blob/master/src/build_data/windows/installer/brickd_installer.nsi.template#L177)

RMDir /R "$INSTDIR"

This isn't best practice:

Warning: using RMDir /r $INSTDIR in the uninstaller
is not safe. Though it is unlikely, the user might select to install to
the Program Files folder and so this command will wipe out the entire
Program Files folder, including other programs that has nothing to do
with the uninstaller. The user can also put other files but the
program's files and would expect them to get deleted with the program.
Solutions are available for easily uninstalling only files which were installed by the installer.

https://nsis.sourceforge.io/Reference/RMDir

The install directory ($INSTDIR) is saved in the registry after a successful install and then fetched again in the uninstaller. If not fetched from the registry manually (via a ReadRegStr) then it is set to $EXEDIR (the location of the uninstaller executable). This can be problematic, especially if a lazy NSIS script writer uses RMDir /r "$INSTDIR".

What if $INSTDIR is empty because the registry key is missing? "$INSTDIR" will become "" which means that everything from the system root could be deleted INCLUDING THE OPERATING SYSTEM. This would also happen if the user ran the uninstaller from C:\ and if that uninstaller did not set $INSTDIR to anything. Also, what if the user has installed to his desktop, or perhaps to My Documents. Need I say more?

https://nsis.sourceforge.io/Validating_$INSTDIR_before_uninstall

In practice the uninstaller will most likely run fine, but fixing the issue sounds like a good idea anyway. Nice side effect would be that your uninstaller is less likely to be flagged by anti virus software.

libusb deprecation warnings

Compiling brickd on Fedora 30 exposes several deprecation warnings:

CC usb.o
usb.c: In function 'usb_create_context':
usb.c:481:3: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
  481 |   libusb_set_debug(*context, 1);
      |   ^~~~~~~~~~~~~~~~
In file included from usb.h:26,
                 from usb.c:33:
/usr/include/libusb-1.0/libusb.h:1300:18: note: declared here
 1300 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~
usb.c:485:3: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
  485 |   libusb_set_debug(*context, 2);
      |   ^~~~~~~~~~~~~~~~
In file included from usb.h:26,
                 from usb.c:33:
/usr/include/libusb-1.0/libusb.h:1300:18: note: declared here
 1300 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~
usb.c:489:3: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
  489 |   libusb_set_debug(*context, 3);
      |   ^~~~~~~~~~~~~~~~
In file included from usb.h:26,
                 from usb.c:33:
/usr/include/libusb-1.0/libusb.h:1300:18: note: declared here
 1300 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~
usb.c:495:4: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
  495 |    libusb_set_debug(*context, 4);
      |    ^~~~~~~~~~~~~~~~
In file included from usb.h:26,
                 from usb.c:33:
/usr/include/libusb-1.0/libusb.h:1300:18: note: declared here
 1300 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~
usb.c:497:4: warning: 'libusb_set_debug' is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
  497 |    libusb_set_debug(*context, 3);
      |    ^~~~~~~~~~~~~~~~
In file included from usb.h:26,
                 from usb.c:33:
/usr/include/libusb-1.0/libusb.h:1300:18: note: declared here
 1300 | void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
      |                  ^~~~~~~~~~~~~~~~

Error controlling multiple stacks

When Controlling 7 stacks of silent stepper bricks via an USB hub, even switching on and off the LED of the bricks gets stuck.

In the log viewer the error I can see the following messages:

        event_winapi.c:184 Starting to poll on 78 USB event source(s)

        2020-07-07 14:32:42.738139 <W> <libusb:check_pollfds> too many HANDLEs to wait on

I traced it down a bit and it looks like libusb cant wait for more than 64 objects.

I get the second message exactly 15 times, since the check for MAXIMUM_WAIT_OBJECTS is "==" this is consistent
with my guess.

However it looks like this has been "fixed" here:

libusb/libusb@c730a84#diff-f4788613f8416e2b052f5d0b145054b0

is it possible to recompile brickd, with the "new" libusb?

Build on openwrt fails

Hi,

currently the build of brickd fails on openwrt because it is missing the daemonlib. After checking the recent changes I found that there is a additional git repo for that. After I added the files of that repo to the source the build of the package was working. I think this could be fixed in the openwrt Makefile.

Thomas

Support not only USB-Devices but also other Brickd's

Idea

The brickd should be able to present other brickd's as if they were locally connected USB-Devices.

Why should you want this?

Because at least when you ship the WiFi-Extension there will be the demand to use it with all old code. The old code does not need to care about relations between IPConnections and devices. One solution to this would be to allow a Brickd to "collect" several other brickd's (e.g. a WiFi-Brick) and present them as local devices.

Who will do this?

Probably me. I am currently looking into the code of the brickd. This is a little pain in the neck, but however some comments made me smile ^^

Is that possible?

You might know the answer, I don't. My current goal is to find out if this is generally possible. So those are my main questions:

  • Do you think this is possible?
  • Do you want to see such a feature? That means: Would you pull it if it works?

I would probably not start coding here, if you say you'd never want such a feature.

Error encountered while executing "make": Too few arguments to function ‘config_init’

Hello, I'm using the latest source code and daemonlib, an error is thrown as follows while I execute "make" to compile the source code:
main_linux.c: In function ‘main’:
main_linux.c:337:2: error: too few arguments to function ‘config_init’
337 | config_init(_config_filename);
| ^~~~~~~~~~~
In file included from main_linux.c:35:
../daemonlib/config.h:145:6: note: declared here
145 | void config_init(const char *filename, bool check_only);
| ^~~~~~~~~~~
make: *** [Makefile:728: main_linux.o] Error 1

add brickd.service file for systemd

Currently the brickd daemon is started via the old init system init.d. Since most distributions moved over to systemd it might make sense to provide a brickd.service file for users. As it stands right now users of ubuntu can not follow the official linux documentation to start the brickd daemon.

Official Linux installation documentation

Installation via .debpackage works (though I would prefer using the package manager for this so I also get updates).
I am able to run the brickd daemon by hand:

$ brickd --version
2.3.1

But trying to run it via the included init.d script fails:

$ sudo /etc/init.d/brickd start
[....] Starting brickd (via systemctl): brickd.serviceFailed to start brickd.service: Unit brickd.service not found.
 failed!

As hinted here the system expects a brickd.service file to exist but can't find it. This seems to be the case for all versions of Ubuntu since 16.04, since a compatibility layer is used

System information

Up to date Ubuntu 16.04.4

Workaround

The simplest way to work around this I found so far is to simply start the daemon by hand when I want to use it:

sudo brickd --daemon

I will see if I can come up with a working .service file when I find the time and comment here if I am successful.

Brick daemon does not compile

When trying to run make for the brick daemon, I am getting the following error multiple times:

client.h:84:19: error: ‘IO’ has no member named ‘handle’
  (int)(client)->io->handle, client_get_authentication_state_name((client)->authentication_state)
                   ^
../daemonlib/log.h:95:76: note: in definition of macro ‘log_message_checked’
      log_message(level, &_log_source, debug_group, __FUNCTION__, __LINE__, __VA_ARGS__); \

I am using Ubuntu-based elementary OS Freya (0.3.2) with GCC 4.8.4, but since client.c does not even compile I appears to me as if there were some problem with the code. I have installed all the dependencies as listed in the README file, and cloned the daemonlib successfully, too.

Failing to build from source

Hello,
during make install i am getting the following error

#: make install
libraries/tools:
- libusb:                1.0.21
- libudev:               not required
- pm-utils:              1.4.1
- systemd:               no
features:
- logging:               yes
- epoll:                 yes
- packet-trace:          no
- debug:                 no
- gprof:                 no
- red-brick:             no
- bricklet:              no
- mesh-single-root-node: no
- hotplug:               libusb
options:
- CFLAGS:                -std=gnu99 -Wall -Wextra -I.. -O2 -DSYSCONFDIR="\"/etc\"" -DLOCALSTATEDIR="\"/var\"" -I/usr/include/libusb-1.0 -DDAEMONLIB_WITH_LOGGING -DDAEMONLIB_WITH_EPOLL -DBRICKD_WITH_USB_REOPEN_ON_SIGUSR1
- LDFLAGS:               -pthread
- LIBS:                  -lrt -lusb-1.0 -ldl
MD /usr/bin
MD /etc
MD /etc/init.d
MD /etc/logrotate.d
MD /var/log
MD /var/run
MD /usr/share
MD /usr/share/man
MD /usr/share/man/man8
MD /usr/share/man/man5
CP brickd
CP brickd.conf
/bin/sh: 1: Syntax error: "(" unexpected
Makefile:569: recipe for target 'install' failed
make: *** [install] Error 2
failed to compile

I am using a Docker-Container to build the brickd with the following settings:

FROM ubuntu:latest

# Update Repos
RUN apt-get update

# Install required Packages
RUN apt-get install -y build-essential pkg-config libusb-1.0-0-dev libudev-dev pm-utils git

# Clone Main Element
RUN git clone https://github.com/Tinkerforge/brickd.git

WORKDIR /brickd/src

# Clone Sub-Repo
RUN git clone https://github.com/Tinkerforge/daemonlib.git

# Set Dir
WORKDIR /brickd/src/brickd

# Make and Install
RUN make
RUN make install

Build on Fedora fails

Hi,
the build on fedora fails, it's something with daemonlib.

[root@localhost brickd]# make
make: *** Aucune règle pour fabriquer la cible « ../daemonlib/array.p », nécessaire pour « ../daemonlib/array.o ». Arrêt.

New feature: relaod USB on USR1 signal

From df50613c05f5f9e4356d62edbdfcdac6f813050b Mon Sep 17 00:00:00 2001
From: Björn <[email protected]>
Date: Sat, 20 Jul 2013 18:41:16 +0200
Subject: [PATCH] added a feature to rescan the USB devices on signal USR1
 this can be used on systems where libudev is not working (like OpenWRT)

---
 src/brickd/event_posix.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/src/brickd/event_posix.c b/src/brickd/event_posix.c
index 67b9a52..87f20d6 100644
--- a/src/brickd/event_posix.c
+++ b/src/brickd/event_posix.c
@@ -28,6 +28,7 @@
 #include "log.h"
 #include "pipe.h"
 #include "utils.h"
+#include "usb.h"

 #define LOG_CATEGORY LOG_CATEGORY_EVENT

@@ -51,6 +52,10 @@ static void event_handle_signal(void *opaque) {
                log_info("Received SIGINT");
        } else if (signal_number == SIGTERM) {
                log_info("Received SIGTERM");
+       }else if (signal_number == SIGUSR1) {
+                log_info("Received SIGUSR1");
+               usb_update();
+               return;
        } else {
                log_warn("Received unexpected signal %d", signal_number);

@@ -110,6 +115,12 @@ int event_init_platform(void) {

                goto cleanup;
        }
+       if (signal(SIGUSR1, event_forward_signal) == SIG_ERR) {
+               log_error("Could install signal handler for SIGUSR1: %s (%d)",
+                       get_errno_name(errno), errno);
+
+               goto cleanup;
+       }

        phase = 5;

--
1.7.0.4

Continuous Write Backlog When Using Callbacks and Delphi Bindings

Continuous Write Backlog When Using Multiple Callbacks and Delphi Bindings

What Happens:

When running a free pascal program with multiple Tinkerforge callbacks the "Writer backlog" warning is going of continuously after some initially stable period. The brickd process then shows high cpu usage, and is not responding properly to connection attempts by other programs (e.g. timeouts in brickv).

Originally this was discovered on a raspberry pi (aarm-64) using multiple callbacks to different bricks and bricklets. The initial period here usually lasted a couple of hours (2-5). I was then able to reproduce this with a Stepper Brick, a Master Brick and a Silent Stepper Bricklet (v2) on a linux desktop (x86) using the code below. For this the Bricklet was connected to the Master Brick, and both Bricks had their own USB cable. This seems to reliably reproduce the behaviour within 30-40 min, usually less. Similar behaviour was also observed with less Bricks and Callbacks, however not in a reliably reproducible manner.

program plsBug;

{$ifdef FPC}{$mode OBJFPC}{$H+}{$endif}

uses
  IPConnection, BrickStepper, BrickletSilentStepperV2, BrickMaster;

type
  TExample = class
  private
    ipcon: TIPConnection;
    stepper: TBrickStepper;
    steplet: TBrickletSilentStepperV2;
    master: TBrickMaster;
  public
    procedure Execute;
  end;

const
  HOST = 'localhost';
  PORT = 4223;
  UIDStepper = 'XXYYZZ';     { Change XXYYZZ to the UID of your Stepper Brick }
  UIDSteplet = 'YYXXZZ';     { Change YYXXZZ to the UID of your Silent Stepper Bricklet }
  UIDMaster = 'ZZXXYY';      { Change ZZXXYY to the UID of your Master Brick }
var
  e: TExample;

procedure TExample.Execute;
begin

  ipcon := TIPConnection.Create;
  stepper := TBrickStepper.Create(UIDStepper, ipcon);
  steplet := TBrickletSilentStepperV2.Create(UIDSteplet, ipcon);
  master := TBrickMaster.Create(UIDMaster, ipcon);

  ipcon.Connect(HOST, PORT);

  { Activating some callbacks with 1ms period }
  stepper.SetAllDataPeriod(1);
  steplet.SetAllCallbackConfiguration(1);
  master.SetStackCurrentCallbackPeriod(1);
  master.SetStackVoltageCallbackPeriod(1);
  master.SetUSBVoltageCallbackPeriod(1);

  while 1=1 do
  begin
  end;
end;

begin
  e := TExample.Create;
  e.Execute;
  e.Destroy;
end.

The code was compiled with fpc -Fu./tinkerforge/source plsBug.pas where the tinkerforge bindings where placed in the same folder, as the source code.

Investigation Thus Far

Other Languages

The first thing I tried was to reproduce this in other languages. An identical python/C program however ran stable for over an hour/over night without showing the behaviour. This most likely places the actual problem somewhere in the non generated files found in /Tinkerforge/generators/delphi.

Debugging Within brickd

I then went ahead and logged the length of the backlog writer->backlog.count whenever it was greater than 0, inside the writer_write function in writer.c. Here it seems that the length , once non zero, keeps incrementing with each call. To my understanding this means, that once a packet is placed in the backlog, it never gets removed from there.

Further logging the header of the input packet shows, that the received packages are (as one would expect) indeed from the callbacks.

netstat

When monitoring tcp connections with netstat -tn one can see that the Recv-Q for the program there fills up prior to the backlog within brickd itself. At this point I however have not dug deep enough into the code to give an interpretation of this. (Delphi implementation of IPConnection not receiving stuff properly?)

Current Guess

My best guess at the moment would be that something goes wrong in the communication between the Delphi implementation of the IPConnection and brickd leading to backlogged packages either not being properly transmitted, or not removed from the backlog when successfully transmitted.

There is also a chance this is the symptom of a general backlogging problem. Maybe python and C are just a lot less likely to ever cause a backlogged packet.

I will keep investigating this problem and post my findings in this thread. If anyone reading this has a good idea about where to look next it will be appreciated :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.