Appdaemon wiringpi errors

Hi again,

Couple of issues in using wiringpi:

  1. In order to run appdaemon need to prefix the command line with sudo. Is this a problem?
  2. It runs fine with sudo prefix, but any changes made to the module whilst appdaemon is running cause the following error to be reported:
    “You must only call this once per program run. This is a fatal error. Please fix your code.”
    resulting in appdaemon stopping and returning to the command line.
    Cause as I understand is due to any change made within the py module forces AD to reload the module.
    In order to resolve this issue, the following code: wiringpi.wiringPiSetupGpio() can only be called once.
    My only other option whilst in the development mode once appdaemon has started, to # out the above.
    Any suggestion appreciated.

Current code within my module as follows:
import appdaemon.appapi as appapi
import wiringpi

fancontrol=18	
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(fancontrol,2)
wiringpi.pwmSetClock(50000)
wiringpi.pwmSetRange(1024)
wiringpi.pwmSetMode(0)

Thanks,

Rob.
P.S. wiringpi is the only library that I’ve found to support the PI inbuilt hardware pulse width modulation on a GPIO18 pin

You don’t need to do this in general but if it has to run as root for wiringpi it shouldn’t be an issue.

The way Apps are designed, they have to be able to be reloaded at any time and reconstruct their state, that is pretty fundamental to the way it works.

In order to avoid calling this multiple times per AppDaemon run you could maybe use a an entry in the global dictionary to note that you have called it already and then only call it if the entry was absent.

Thanks Andrew,

Could you please point me in the direction of creating an entry in a global dictionary?
Have searched and not clear what I need to do.

What I’m thinking is to place a condition within my module:
if condition != “alreadyinialised” :wiringpi.wiringPiSetupGpio()
then straight after do:
condtion=“alreadyinitialsed”

is there a close function from the wiringpi?
if yes then you could set the close function in the terminate function if i am correct.
that way, if the app closes, also the wiringpi closes and restart wouldnt give a problem anymore.

That’s the basic idea. I’m away from my desktop at the moment but look in the he API docs for the section called “Sharing information between apps”. Any value in global_vars will survive an app restart.

Thanks Rene,

Had a look, doesn’t appear to have that function.

Thanks Andrew,

Struggling a bit on the structure.
But would be handy, (i love working examples)
Of what I would put in the appdaemon.cfg
ie var would be:
condition
value would be:
alreadyinitialsed

Rob.

i think i would go another way.

create a general app where you create wiringpi functions you need, including a wiringpi init
then from any other app call those not init functions with get_app

then you only need to restart appdaemon if you add/change wiringpi functions to your general app.

It’s not n the config, it’s a Python dictionary you can use within your Apps.

Also, Rene’s suggestion is a good one. I’ll type more when I’m not on my phone!

1 Like

Appreciated…again Andrew.

Rob.

Sorry skipped over this one Rene,

Yep. possible and good idea, but the challenge is when to know if AD has started to ensure the function only gets called once.

Not exactly sure what the wiringpi setup function does but it may just setup the hardware. Hence any app inside AD or externally could setup the hardware. Something to test…

I’m heading away to a remote island for work, so won’t be able to play with my PI until my return next week. But will keep an eye on this topic.

Rob.

if you use the initialize from the general app for the wiringpi part that only need to be called once, they only can be called once.
so your general app would be like:

import appdaemon.appapi as appapi
import wiringpi

class(mywiringpi):

  def initialize(self):
    self.fancontrol=18
    wiringpi.wiringPiSetupGpio()
    wiringpi.pinMode(self.fancontrol,2)
    wiringpi.pwmSetClock(50000)
    wiringpi.pwmSetRange(1024)

  def digitalwrite(self,pin,value):
    wiringpi.DigitalWrite(pin,value)

  def fan_on(self):
    wiringpi.DigitalWrite(self.fancontrol,1)

  def fan_off(self):
    wiringpi.DigitalWrite(self.fancontrol,0)

in the config:

[wipi]
module = mywiringpi
class = mywiringpi

in your other apps you then would use it like:

import appdaemon.appapi as appapi

class(thermostat):

  def initialize(self):
    self.listen_state(self.temp_controlled,"sensor.your_temperature_sensor")

  def temp_controlled(self, entity, attribute, old, new, kwargs):
    wipi = self.get_app("wipi")
    if (float(new)>30.0):
      wipi.fan_on()
    if (float(new)<29.0):
      wipi.fan_off()

remember i just wrote this out of my head without any testing so it could be with a lot of failures, but it should give you a idea how to go on.

while posting this i saw that what you posted as your code in the first posting, is not an app.
that also could cause a part of your problems.

an app should Always have the lines class and initialize

Looks good Rene!

That makes logical sense, and you’ve also shown me how to pass info between apps!
I’m slowly getting my head around the structure.

Big thanks again,

Rob.

1 Like

you also can make an input_boolean in hass.
in the general app you set a listen_state to that boolean and if the boolean goes on you use the fan_on and if it goes off you use the fan_off.

from that moment you dont even need to call the general app anymore for your fan, you just use the boolean in your apps.
( in fact that would have created your own custom wiringpi component :wink: )

This may be wandering a little off topic here, but it’s kind of related. The depends argument in the config file would make sure the app is up and running and would keep it from being loaded twice. RIght? Also, I’ve been trying to watch for this, but there are to many messages in the log for me to follow it completely. on a Hass restart, do the apps load in the order they are in the config file?

i dont know if @aimc did set it up that way.
as i understood it, it is that if you use the dependency, then will both apps be restarted if you change something in 1. (or actually just the top app)
i didnt mention it because restarting the general app is just what we would like to avoid.

i think that the apps start in order from the config, but in different threads, so actually they start simultaniously. making that the fastest app will be completely started first.
it would be nice if we could give a startorder and delay for apps, but havent asked about that (yet)

The dependency would ensure it was loaded first, it is not responsible for keeping it running.

Absolutely not!

That is the whole point of depends, if a module has a dependency, the dependency has to be loaded first regardless of the order in the config file.

The order of loading is not specifically defined, other than to say that any modules that others depend on will be loaded ahead of that module. This works for multiple module dependency chains too.

will the depending apps start after a complete load? and how is checked if everything is running?
will the depending apps not be loaded if the top app is in error?

The dependencies are enforced at startup time and also if an app is modified that others depend on.

It’s up to you to decide if an App is “running” - its hard to say what that means.

If an app fails compilation, the object will not exist and your other apps will get errors trying to access it. If you then fix the error, AppDaemon will reload the Original App as well as the dependant apps and it should all work.

if the top app has 25 commands in the init, will the depending apps start AFTER all commands are done? or will they start loading earlier?

or the better question:
how to make sure, that everything i want to be done in a general app, is completed before the depending apps start?