[Solved] Using GPIO from tinkerboard

Hello forum,
I’m trying the simplest thing like have my Asus Tinker Board acting as controller for few things.
First nightmare, installing a different distro than what is in the Asus perspective: Archlinux. There’s very little that fit in a mainlined kernel.
Second nightmare, trying to get a server running. Too many programs for a simple private network operations (Apache2, php, python, bash)
Third nightmare, getting hass working somewhere. The hassos doesn’t recognize the GPIO. Accessing the docker container is another complex story, the normally writing to/sys/classes/gpio doesn’t seem to be allowed.
Isn’t it frustrating?
Doesn’t anybody have a little experience to share ?

QUESTION
What am I supposed to do ?

  1. I’m trying to repack the docker, but I’d like to know how it would be modified with the necessary bits to allow the correct access to the GPIO.
  2. I’m keen that there could be a way to add program to the hassos in order to have access to the GPIO.
  3. It will be nice if hassos allows wiring programs to be installed, same issue as point 2.

I hope some developer help…

Square peg, meet round hole.

Well, we may file the edges and see if it will fit :slight_smile:
My actual intention is to open the container, because ALarm has a problem to get solved.

But I’d say that it’s the hassos needs to update py-yaml.

I took another approach. Installing homeassistant on the TinkerOS (aka linaro). After few initial difficulties the installation is done by pip install.
I’m not seeing results yet. but looks like it’s proceeding to initiate the system.

I hope that soon I’ll get to handle with the GPIO.
I GOT it :smiley: proceeding for the intial settings on the web-ui :stuck_out_tongue:

EDIT
HA is up and I got something configured. It seems that the ffmpeg camera are more responsive than from inside the docker.
I think I’ll have something working on the GPIO, but I should have to add my own component. Slightly different from rpi_gpio. Any suggestion to make HA seeing my custom component?
Road won’t be smooth, anyways, the python version from linaro will be deprecated next month :cry::worried:

I learnt other methods. I added the Asus library so the call is overloaded by the local in /custom_components/.
Then I modified the rpi_gpio to reflect the new change. I tried to call the new component, but it doesn’t do anything.
I just tried to call the service.
Any idea to enable the debugging ?

Home assistant produces logs by default. If you want to adjust the logging level, look for the logger integration.

I saw it, but I don’t see any signal if I set my logging on the program and starting the service
So the program is just the copy of rpi_gpio, but is calling a different module.
homeassistant/custom_components/asus_gpio/switch.py

"""Allows to configure a switch using RPi GPIO."""
import logging

import voluptuous as vol

from homeassistant.components.switch import PLATFORM_SCHEMA
import asus_gpio
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.helpers.entity import ToggleEntity
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

CONF_PULL_MODE = 'pull_mode'
CONF_PORTS = 'ports'
CONF_INVERT_LOGIC = 'invert_logic'

DEFAULT_INVERT_LOGIC = False

_SWITCHES_SCHEMA = vol.Schema({
    cv.positive_int: cv.string,
})

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_PORTS): _SWITCHES_SCHEMA,
    vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
})


def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Raspberry PI GPIO devices."""
    invert_logic = config.get(CONF_INVERT_LOGIC)

    switches = []
    ports = config.get(CONF_PORTS)
    for port, name in ports.items():
        switches.append(ASUSGPIOSwitch(name, port, invert_logic))
    add_entities(switches)


class ASUSGPIOSwitch(ToggleEntity):
    """Representation of an Asus Tinker Board GPIO."""

    def __init__(self, name, port, invert_logic):
        """Initialize the pin."""
        self._name = name or DEVICE_DEFAULT_NAME
        self._port = port
        self._invert_logic = invert_logic
        self._state = False
        asus_gpio.setup_output(self._port)
        asus_gpio.write_output(self._port, 1 if self._invert_logic else 0)

    @property
    def name(self):
        """Return the name of the switch."""
        return self._name

    @property
    def should_poll(self):
        """No polling needed."""
        return False

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state

    def turn_on(self, **kwargs):
        """Turn the device on."""
        asus_gpio.write_output(self._port, 0 if self._invert_logic else 1)
        self._state = True
        self.schedule_update_ha_state()

    def turn_off(self, **kwargs):
        """Turn the device off."""
        asus_gpio.write_output(self._port, 1 if self._invert_logic else 0)
        self._state = False
        self.schedule_update_ha_state()

This is the
homeassistant/configuration.yaml

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Uncomment this if you are using SSL/TLS, running in Docker container, etc.
# http:
#   base_url: example.duckdns.org:8123

# Text to speech
tts:
  - platform: google_translate

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml

frontend:
  themes: !include_dir_named themes

camera:
  - platform: ffmpeg
    name: Gate
    input:  rtmp://xxx.xxx.xxx.xxx:1935/flash/11:<user>:<password>
  - platform: ffmpeg
    name: SideDoor
    input:  rtmp://xxx.xxx.xxx.xxx:1935/flash/11:<user>:<password>
switch:
  - platform: asus_gpio
    ports:
      14: Gate
      15: Pillar Lights
      18: Extra
      invert_logic: true
logger:
  default: info
  logs:
    custom_components.switch: debug

I’m trying to call the service like switch.turn_on which would trigger switch.gate or the other two option. But nothing is coming on the log.
There are also two other way to access the GPIO and they work. So the difference between RPi and Asus is minimal, I’d say transparent.
I just tried with this small program

#!/usr/bin/env python3

from ASUS import GPIO
import time

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
LED1 = 8
LED2 = 10
LED3 = 12
GPIO.setup(LED1,GPIO.OUT)
GPIO.setup(LED2,GPIO.OUT)
GPIO.setup(LED3,GPIO.OUT)
try:
    while True:
        for led in (LED1, LED2, LED3):
            GPIO.output(led,GPIO.HIGH)
            time.sleep(0.5)
            GPIO.output(led,GPIO.LOW)
            time.sleep(0.5)
except KeyboardInterrupt:
    GPIO.cleanup()

EDIT
Also testing the functions doesn’t represent any issue

 $ sudo python3 -q
>>> from ASUS import GPIO
>>> GPIO.setmode(GPIO.BCM)
>>> GPIO.cleanup()
__main__:1: RuntimeWarning: No channels have been set up yet - nothing to clean up!  Try cleaning up at the end of your program instead!
>>> def setup_output(port):
...     """Set up a GPIO as output."""
...     from ASUS import GPIO  # pylint: disable=import-error
...     GPIO.setup(port, GPIO.OUT)
... 
>>> def write_output(port, value):
...     """Write a value to a GPIO."""
...     from ASUS import GPIO  # pylint: disable=import-error
...     GPIO.output(port, value)
... 
>>> def read_input(port):
...     """Read a value from a GPIO."""
...     from ASUS import GPIO  # pylint: disable=import-error
...     return GPIO.input(port)
... 
>>> def edge_detect(port, event_callback, bounce):
...     """Add detection for RISING and FALLING events."""
...     from ASUS import GPIO  # pylint: disable=import-error
...     GPIO.add_event_detect(
...         port,
...         GPIO.BOTH,
...         callback=event_callback,
...         bouncetime=bounce)
... 
>>> set
set(           setattr(       setup_output(  
>>> setup_output(14)
This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
>>> GPIO.setwarnings(False)
>>> setup_output(14)       
>>> setup_output(15)
>>> setup_output(18)
>>> write_output(14,1)
>>> write_output(14,0)
>>> write_output(15,1) 
>>> write_output(15,0)
>>> write_output(18,1) 
>>> write_output(18,0)
>>> read_input(18)
0
>>> write_output(18,1)
>>> read_input(18)    
1
>>> write_output(18,0)    
>>> read_input(18)    
0
>>> GPIO.cleanup()
$ python3 -q
>>> from ASUS import GPIO
>>> GPIO.setmode(GPIO.BOARD)
>>> LED1 = 8
>>> GPIO.setup(LED1,GPIO.OUT)
can't open /dev/mem and /dev/gpiomem
wiringPiSetup: Unable to open /dev/mem and /dev/gpiomem: No such file or directory
Segmentation fault
=================================================================
Jul 09 19:06:06 tinkerboard hass[7601]: 2019-07-09 19:06:06 INFO (MainThread) [homeassistant.setup] Setup of domain asus_gpio took 0.1 seconds.
Jul 09 19:06:06 tinkerboard hass[7601]: 2019-07-09 19:06:06 INFO (MainThread) [homeassistant.components.switch] Setting up switch.asus_gpio
Jul 09 19:06:06 tinkerboard systemd[1]: [email protected]: Main process exited, code=killed, status=11/SEGV
Jul 09 19:06:06 tinkerboard systemd[1]: [email protected]: Failed with result 'signal'.

Here’s the matter. The ASUS module needs permissions to create several devices in /dev. Only when an admin is working with it all is fine.

I need some guide to solve this.
Mainwhile I moved the ASUS module under homeassistant components and the module exists in site-packages of python3.

I’m trying to setup a daemon that will work with admin privileges, so I can send the commands to that.
May MQTT broker work in such manner ?

My solution :
I implemented an interface to call the program gpio from wiringPi which may be used for RPi as well.
I don’t have an idea regarding the callback, yet.

any progress on this? would be nice to hook up some things on the GPIO’s from the tinkerboard

My progress are frozen, due by lack of free time. Anyways I can manage to use the GPIO, but no options yet to trigger an event for the inputs. I still experimenting with gpio (the program) whether it’s able to give an event.
I hope to resume, around Xmas.

1 Like