Giter VIP home page Giter VIP logo

gpio's Issues

Flyweight pattern

Should the flyweight pattern be used (so that there is only ever one instance of any pin as they are remembered by the factory)?

For

  • Reduces memory
  • Increases performance (especially if pins auto export or configure on construction)

Against

  • Memory and performance differences could be insignificant
  • Might make it more difficult to switch a pin from an input to an output pin. Primary key would have to be number + direction rather than just number.

Again - interested to hear thoughts?

Permission denied for /sys/class/gpio/export

OK, I really believe I have tried everything. I am constantly getting the permission fatal error:

PHP Fatal error: Uncaught RuntimeException: fopen(/sys/class/gpio/export): failed to open stream: Permission denied in /var/www/html/vendor/piphp/gpio/src/FileSystem/FileSystem.php:55

I've tried every solution I was able to find online. I've tried adding www-data user to gpio group, which strangely resulted in Apache not starting at all (not sure why). I even tried dumb last resorts as setting permissions to 777 of whole /sys/class/gpio folder recursively, or adding unlimited access to www-data user in /etc/sudoers.

Still the same error. Any help?

Under New Management :D

This morning @AndrewCarterUK put out a call for a new maintainer: https://twitter.com/AndrewCarterUK/status/1291697455663325184

@Sam-Burns and I offered to step in and take over the project and I'm excited to say hello and share some initial plans with everyone.

A general outline of my plans for the GPIO project:

  • review/merge/decline the PRs as needed.
  • Figure out what PHP versions we should support
  • Swap to Github Actions because why not?! :D
  • Start refactoring to support newer PHP versions

I'd love to know what OS our users are using on their Pis, here is a short straw poll: http://www.strawpoll.me/20734890

Raspberry Pi OS has PHP 7.0 -> 7.3 it seems. I think we start with 7.3 as a base target of compatibility and drop everything from there unless there is a very pressing need? If you have such a use case please comment!

If you have any questions for us please ask them here!

php version not declared

No php version is declared, indeed the whole "require" section is missing from composer.json (didn't look at code, so maybe some other ext could be missing too)

PHP 7

Hi,
Does it works on PHP7 ?

Permissions are not set, pelase provide example

Hi There.

I am sorry to bring this up, but could the permissions settings also be addressed here, because this does not work without them.

When user starts this from the pure clean jessie image and installs apache2 with php5, GPIO permissions are not right

Thank you for your considerations.

How to use PWM ?

I didn't found any PWM support in this library, how do you achieve this ?

Pins multiple times exported

Nice to see this project has new life!

I however came across a bug which might be my fault. I am subscribing to a MQTT server and it stays connected listening for new messages to come in.

Inside that loop, I had the following code:

foreach ($subscribe->loop($client) as $message) {
    // bla bla bla, some irrelevant code
    if ($stateFile['command'] !== $command) {
        $gpio = new GPIO();
        $pin = $gpio->getOutputPin(RELAY_PIN);

         if ($command === 'on') {
            $pin->setValue(PinInterface::VALUE_LOW);
        } else {
            $pin->setValue(PinInterface::VALUE_HIGH);
        }
    }
}

This meant that the first time this code was called, everything went ok. The second time however, it errored out:

PHP Fatal error:  Uncaught RuntimeException: fwrite(): write of 2 bytes failed with errno=16 Device or resource busy in /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/FileSystem/FileSystem.php:54
Stack trace:
#0 /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/FileSystem/FileSystem.php(45): PiPHP\GPIO\FileSystem\FileSystem->exceptionIfFalse()
#1 /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/Pin/Pin.php(115): PiPHP\GPIO\FileSystem\FileSystem->putContents()
#2 /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/Pin/Pin.php(55): PiPHP\GPIO\Pin\Pin->writePinNumberToFile()
#3 /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/Pin/Pin.php(39): PiPHP\GPIO\Pin\Pin->export()
#4 /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/Pin/OutputPin.php(17): PiPHP\GPIO\Pin\Pin->__construct()
#5 /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/GPIO.php(41): PiPHP\GPIO\Pin\OutputPin->__construct()
#6 /home/ubuntu/gpio/controlVenti in /home/ubuntu/gpio/controlVentilatorBaseroom/vendor/piphp/gpio/src/FileSystem/FileSystem.php on line 54

I fixed it by moving the following piece of code out of the loop:

$gpio = new GPIO();
$pin = $gpio->getOutputPin(RELAY_PIN);

I've been running this code for a few years now and this wasn't an issue before. I understand the problem and I know it is not desirable to create a new instance of the same pin within the same flow of a program, so here my question: was this a bug on my side or do I make an attempt at trying to fix this one?

Greetings.

Pin::getEdge/setEdge

Edge detection is primarily used for interrupt detection - sometimes we only care about interrupts LOW -> HIGH for example. However, it looks like this is being set via the Pin class (and can be done for output pins, which isn't useful). Would it make more sense to set this on the interrupt watcher instead?

State of output pins

Creating a new 'output pin' instance rewrites to the sysfs GPIO direction file and resets the pin state.

Solution is to check to see if the pin is already an output pin and only write to the direction file if it isn't.

Tag: @alfredomova

MCP23017

Does this support extending GPIO's via a MCP23017 chip?

Set direction in constructor?

Many other GPIO libraries require you to set the direction at the same time the pin is declared for use - either via the constructor or some other initialization function. This makes sense, because you're probably never going to change the direction of a pin during execution without rewiring your project.

Would it make sense to do the same thing with the Pin class? Basically change its constructor to include a $direction parameter? Or alternatively create separate InputPin and OutputPin classes, where the setValue() method is only available on the latter?

I'd be happy to submit a PR for either change if you're interested.

InterruptWatcher always fires callback immediately

I cannot seem to get the interrupt functionality working - my callback is always fired immediately, regardless of the timeout I set or the state of the pin.

I'm using the exact code from the README, but with two changes:

  • I'm using GPIO4 (4 in the code)
  • I'm trying different timeout values like 999999

The screen floods with these messages:

Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1

If I change the state of the pin, I'll see the value change accordingly:

Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 1

But the callback still fires rapidly when the state isn't changing.

I tried testing the underlying stream_select() myself by running the following commands as root...

echo 4 > /sys/class/gpio/unexport # Start from a clean state

echo 4 > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio4/direction
echo "both" > /sys/class/gpio/gpio4/edge

Followed by this PHP script as root:

<?php

$r = $w = [];
$e = [fopen('/sys/class/gpio/gpio4/value', 'r')];

$val = stream_select($r, $w, $e, 99999);

var_dump($val);

The script immediately ends with the following output:

int(1)

This occurs both when nothing is connected to the pin (value is HIGH) and when the pin is connected directly to GND (value is LOW).

I wonder if perhaps this only occurs with certain Pi devices? I'm using a Raspberry Pi 3 running Raspbian Jessie.

Add static analyse like phpstan

Hello,

i try add static analyse tool phpstan to project and here is output and choise what to do.

Here is commit where are changes https://github.com/h4kuna/GPIO/commit/93fa0c099d61d0a9fb9b2e3eb97032034ecfef8e run it by ./test/phpstan.

1 strict php functions

I will create new class with this php funcions what return two value and make it strictly like this. But here is need only fopen, fwrite and stream_get_contents.

And create own excenption instead of global RuntimeException.

 ------ --------------------------------------------------------------------------------------------------------------------------------- 
  Line   src/FileSystem/FileSystem.php                                                                                                    
 ------ --------------------------------------------------------------------------------------------------------------------------------- 
  29     Method PiPHP\GPIO\FileSystem\FileSystem::getContents() should return string but returns resource.                                
  29     Parameter #1 $result of method PiPHP\GPIO\FileSystem\FileSystem::exceptionIfFalse() expects resource|false, string|false given.  
  42     Method PiPHP\GPIO\FileSystem\FileSystem::putContents() should return int but returns resource.                                   
  42     Parameter #1 $result of method PiPHP\GPIO\FileSystem\FileSystem::exceptionIfFalse() expects resource|false, int|false given.     
  53     Offset 'message' does not exist on array('type' => int, 'message' => string, 'file' => string, 'line' => int)|null.              
 ------ --------------------------------------------------------------------------------------------------------------------------------- 

2 php typehint

Here are two way, make it strtly by php typehint or for this moment only by annotation. I'm vote for first choice and support with php 7.3+, it will be BC break. Here is opended PR #38

 ------ --------------------------------------------------------------------------------------------------- 
  Line   src/GPIO.php                                                                                       
 ------ --------------------------------------------------------------------------------------------------- 
  14     Property PiPHP\GPIO\GPIO::$fileSystem has no typehint specified.                                   
  15     Property PiPHP\GPIO\GPIO::$streamSelect has no typehint specified.                                 
  40     Method PiPHP\GPIO\GPIO::getOutputPin() has parameter $exportDirection with no typehint specified.  
 ------ --------------------------------------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------------------------------- 
  Line   src/Interrupt/InterruptWatcher.php                                                            
 ------ ---------------------------------------------------------------------------------------------- 
  10     Property PiPHP\GPIO\Interrupt\InterruptWatcher::$fileSystem has no typehint specified.        
  11     Property PiPHP\GPIO\Interrupt\InterruptWatcher::$streamSelect has no typehint specified.      
  12     Property PiPHP\GPIO\Interrupt\InterruptWatcher::$streams has no typehint specified.           
  13     Property PiPHP\GPIO\Interrupt\InterruptWatcher::$pins has no typehint specified.              
  14     Property PiPHP\GPIO\Interrupt\InterruptWatcher::$callbacks has no typehint specified.         
  43     Method PiPHP\GPIO\Interrupt\InterruptWatcher::register() has no return typehint specified.    
  62     Method PiPHP\GPIO\Interrupt\InterruptWatcher::unregister() has no return typehint specified.  
  78     Method PiPHP\GPIO\Interrupt\InterruptWatcher::watch() has no return typehint specified.       
 ------ ---------------------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------------------- 
  Line   src/Interrupt/InterruptWatcherInterface.php                                                            
 ------ ------------------------------------------------------------------------------------------------------- 
  15     Method PiPHP\GPIO\Interrupt\InterruptWatcherInterface::register() has no return typehint specified.    
  22     Method PiPHP\GPIO\Interrupt\InterruptWatcherInterface::unregister() has no return typehint specified.  
  29     Method PiPHP\GPIO\Interrupt\InterruptWatcherInterface::watch() has no return typehint specified.       
 ------ ------------------------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------- 
  Line   src/Pin/InputPin.php                                                         
 ------ ----------------------------------------------------------------------------- 
  36     Method PiPHP\GPIO\Pin\InputPin::setEdge() has no return typehint specified.  
 ------ ----------------------------------------------------------------------------- 

 ------ -------------------------------------------------------------------------------------- 
  Line   src/Pin/InputPinInterface.php                                                         
 ------ -------------------------------------------------------------------------------------- 
  24     Method PiPHP\GPIO\Pin\InputPinInterface::setEdge() has no return typehint specified.  
 ------ -------------------------------------------------------------------------------------- 

 ------ ----------------------------------------------------------------------------------------------------------- 
  Line   src/Pin/OutputPin.php                                                                                      
 ------ ----------------------------------------------------------------------------------------------------------- 
  15     Method PiPHP\GPIO\Pin\OutputPin::__construct() has parameter $exportDirection with no typehint specified.  
  31     Method PiPHP\GPIO\Pin\OutputPin::setValue() has no return typehint specified.                              
 ------ ----------------------------------------------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------------------------- 
  Line   src/Pin/OutputPinInterface.php                                                          
 ------ ---------------------------------------------------------------------------------------- 
  12     Method PiPHP\GPIO\Pin\OutputPinInterface::setValue() has no return typehint specified.  
 ------ ---------------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------------ 
  Line   src/Pin/Pin.php                                                                                 
 ------ ------------------------------------------------------------------------------------------------ 
  27     Property PiPHP\GPIO\Pin\Pin::$fileSystem has no typehint specified.                             
  28     Property PiPHP\GPIO\Pin\Pin::$number has no typehint specified.                                 
  30     Property PiPHP\GPIO\Pin\Pin::$exported has no typehint specified.                               
  57     Method PiPHP\GPIO\Pin\Pin::export() has no return typehint specified.                           
  72     Method PiPHP\GPIO\Pin\Pin::unexport() has no return typehint specified.                         
  82     Method PiPHP\GPIO\Pin\Pin::isExported() has no return typehint specified.                       
  92     Method PiPHP\GPIO\Pin\Pin::getDirection() has no return typehint specified.                     
  106    Method PiPHP\GPIO\Pin\Pin::setDirection() has no return typehint specified.                     
  106    Method PiPHP\GPIO\Pin\Pin::setDirection() has parameter $direction with no typehint specified.  
  163    Method PiPHP\GPIO\Pin\Pin::writePinNumberToFile() has no return typehint specified.             
 ------ ------------------------------------------------------------------------------------------------ 

 ------ ---------------------------------------------------------------------------------- 
  Line   src/Pin/PinInterface.php                                                          
 ------ ---------------------------------------------------------------------------------- 
  20     Method PiPHP\GPIO\Pin\PinInterface::export() has no return typehint specified.    
  25     Method PiPHP\GPIO\Pin\PinInterface::unexport() has no return typehint specified.  
 ------ ---------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------------------ 
  Line   test/FileSystem/FileSystemTest.php                                                                    
 ------ ------------------------------------------------------------------------------------------------------ 
  11     Method PiPHP\Test\GPIO\FileSystem\FileSystemTest::testFileSystem() has no return typehint specified.  
  34     Method PiPHP\Test\GPIO\FileSystem\FileSystemTest::testBadFile() has no return typehint specified.     
 ------ ------------------------------------------------------------------------------------------------------ 

 ------ ---------------------------------------------------------------------------------------------------------------- 
  Line   test/Pin/OutputPinTest.php                                                                                      
 ------ ---------------------------------------------------------------------------------------------------------------- 
  12     Method PiPHP\Test\GPIO\Pin\OutputPinTest::testOutputPin() has no return typehint specified.                     
  28     Method PiPHP\Test\GPIO\Pin\OutputPinTest::testOutputPinIsNotDoubleExported() has no return typehint specified.  
 ------ ---------------------------------------------------------------------------------------------------------------- 

 ------ ------------------------------------------------------------------------------------------- 
  Line   test/Pin/InputPinTest.php                                                                  
 ------ ------------------------------------------------------------------------------------------- 
  11     Method PiPHP\Test\GPIO\Pin\InputPinTest::testInputPin() has no return typehint specified.  
 ------ ------------------------------------------------------------------------------------------- 

3 fix tests

Tests have specific errors. I will fix it at last.

 ------ --------------------------------------------------------------------------------------------------------- 
  Line   test/FileSystem/VFS.php                                                                                  
 ------ --------------------------------------------------------------------------------------------------------- 
  9      Property PiPHP\Test\GPIO\FileSystem\VFS::$vfs has no typehint specified.                                 
  11     Method PiPHP\Test\GPIO\FileSystem\VFS::open() should return resource but return statement is missing.    
  22     Method PiPHP\Test\GPIO\FileSystem\VFS::putContents() should return int but return statement is missing.  
  30     Parameter #2 $subject of function preg_match expects string, int|string given.                           
 ------ --------------------------------------------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------------------------------- 
  Line   test/Interrupt/InterruptWatcherTest.php                                                       
 ------ ---------------------------------------------------------------------------------------------- 
  11     Method PiPHP\Test\GPIO\InterruptWatcherTest::testWatcher() has no return typehint specified.  
  17     Cannot access offset 1 on array<resource>|false.                                              
  18     Cannot access offset 1 on array<resource>|false.                                              
  27     Cannot access offset 0 on array<resource>|false.                                              
  28     Cannot access offset 0 on array<resource>|false.                                              
  69     Cannot access offset 1 on array<resource>|false.                                              
  72     Cannot access offset 1 on array<resource>|false.                                              
  73     Cannot access offset 1 on array<resource>|false.                                              
  79     Cannot access offset 1 on array<resource>|false.                                              
  86     Cannot access offset 1 on array<resource>|false.                                              
  87     Cannot access offset 1 on array<resource>|false.                                              
 ------ ---------------------------------------------------------------------------------------------- 

EDGE_RISING behaving like EDGE_BOTH

First of all, I see no activity in this repo since a while ago, and even if I'm currently using it in a project of mine, are there any reasons that I shouldn't?

Now to the question.
First version of my code was using:
$pin[$sensore]->setEdge(InputPinInterface::EDGE_BOTH);

but then I realized I only was actually inerested to check when the input became from LOW to HIGH, so I changed it to
$pin[$sensore]->setEdge(InputPinInterface::EDGE_RISING);

What I noticed, tho, is that I kept getting the same amount of events of the first version.
It's a motion sensor which is activated, and then deactivates itself after 2-3 seconds, and even if I try and select only EDGE_RISING (activation in this case) I get an event both when sensor activates (LOW->HIGH) and when it deactivates (HIGH->LOW).

Shouldn't matter much as I can prune those event I'm not interested in, I just wonder if it wouldn't use less resources if it worked as intended.

Initial Interrupt

Upon registering the pin with the interrupt watcher there is data available to read in the stream. This causes the watch() method to trigger the callback on the first run of every newly registered pin.

Solution: read pin value file after registering the pin and then add it to the event loop.

Installation guide insufficient

I installed via composer:

$ php composer.phar require piphp/gpio
Using version ^0.4.0 for piphp/gpio
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing piphp/gpio (0.4.0): Downloading (100%)         
Writing lock file
Generating autoload files

And then using this code in /var/www/html/index.php

use PiPHP\GPIO\GPIO;
use PiPHP\GPIO\Pin\PinInterface;

// Create a GPIO object
$gpio = new GPIO();

// Retrieve pin 18 and configure it as an output pin
$pin = $gpio->getOutputPin(4);

// Set the value of the pin high (turn it on)
$pin->setValue(PinInterface::VALUE_HIGH);

Results in

Fatal error: Uncaught Error: Class 'PiPHP\GPIO\GPIO' not found in /var/www/html/index.php:13 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 13

Debouncing interrupts

Do you think there's a need for the InterruptWatcher to have debouncing logic built-in? For example, when I run the code in the README example and toggle the connection between the GPIO pin and ground, I get the following result:

Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 1
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 0
Pin 4 changed to: 1

Note how sometimes the interrupt callback is fired but the value doesn't appear to have changed. This happens because the value rapidly switches (or "bounces") due to noise or mechanical/physical imperfections with the button/connection.

A common approach to "debouncing" is timing the duration between the current interrupt and the previous one. If it's faster than, say, 100ms then the toggle probably wasn't intentional and should be ignored. Here's an example: https://raspberrypi.stackexchange.com/questions/8544/gpio-interrupt-debounce

As a developer I could implement this myself on top of your library, but it would be much easier if that functionality was baked in.

I2C support

Any change to add I2C to this lib ?

i use a lot of I2C boards and usually i use exec() to control them... is not great but it does the job.
something to work on that would be super.

Numbered release

I suggest we do a new numbered release sometime soon, along with the changes to the language version requirements.
@svpernova09 have you got admin access to the Packagist package btw?

Perhaps it would be a good idea to introduce some PHP7 typehinting, before we do that. It would be a BC breaking change, but we could release the library at version 1.0.0 after this and any other pending changes.

Thoughts?

Should pins auto export?

For

  • You pretty much always want to do it if you want a pin instance
  • Reduces boiler plate code
  • Less chance of bugs from forgetting to do it
  • Pin object is unusable unless exported

Against

  • Possibly hidden side affect
  • Could be messy to disable $pin = $factory->getInputPin($num, $autoExport);
  • Might want to export and unexport multiple times during lifetime of app so need the methods anyway

Interested to hear any other thoughts

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.