Announcement: AppDaemon 4.0.0 beta 2

for now it seems not to be, but thats going to change.

Running 4.0.0b2 and trying to use @ad.app_lock as described in section 6.14:

import hassapi as hass
import datetime

class Locking(hass.Hass):
   def initialize(self):
     self.important_var = 0
     now = datetime.datetime.now()
     target = now + datetime.timedelta(seconds=2)
     for i in range (1000):
       self.run_at(self.hass_cb, target)

   @ad.app_lock
   def hass_cb(self, kwargs):
     self.important_var += 1
     self.log(self.important_var)

Getting this error (NameError: name ‘ad’ is not defined):

==> /config/appdaemon/Logs/appdaemonerr.log <==
2019-12-02 23:03:02.195877 WARNING Error: ------------------------------------------------------------
2019-12-02 23:03:02.196936 WARNING Error: Unexpected error loading module: /config/appdaemon/apps/ttt.py:
2019-12-02 23:03:02.198732 WARNING Error: ------------------------------------------------------------
2019-12-02 23:03:02.201931 WARNING Error: Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/appdaemon/app_management.py", line 551, in read_app
    importlib.reload(self.modules[module_name])
KeyError: 'ttt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/appdaemon/app_management.py", line 773, in check_app_updates
    await utils.run_in_executor(self, self.read_app, mod["name"], mod["reload"])
  File "/usr/lib/python3.7/site-packages/appdaemon/utils.py", line 277, in run_in_executor
    response = future.result()
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/lib/python3.7/site-packages/appdaemon/app_management.py", line 556, in read_app
    self.read_app(file)
  File "/usr/lib/python3.7/site-packages/appdaemon/app_management.py", line 565, in read_app
    self.modules[module_name] = importlib.import_module(module_name)
  File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/config/appdaemon/apps/ttt.py", line 4, in <module>
    class Locking(hass.Hass):
  File "/config/appdaemon/apps/ttt.py", line 12, in Locking
    @ad.app_lock
NameError: name 'ad' is not defined

2019-12-02 23:03:02.203259 WARNING Error: ------------------------------------------------------------

What am I missing?

Thanks!

I assume it’s the import of the appdaemon library that you are missing.

import adbase as ad

1 Like

where do i find section 6.14?

I think he’s referring to this document https://buildmedia.readthedocs.org/media/pdf/appdaemon/dev/appdaemon.pdf

1 Like

thx. i didnt even know that existed :wink:

Me neither until I did a google search for ad.app_lock appdaemon, it seems the document is from 2 days ago :slight_smile:

i guess its an option from readthedocs.
andrew updated dev 2 days ago, so there is new stuff in the docs.

Thank you - that was it!

One more question … I am trying to set production mode on/off using the service call:

self.call_service("production_mode/set", mode=False, namespace="appdaemon")

and I get the following WARNING:

WARNING AppDaemon: Unknown domain (appdaemon/production_mode) in call_service from ADProdMode

Here’s the code:

import hassapi as hass
import datetime
import adbase as ad

class ADProdMode(hass.Hass):
   def initialize(self):
     self.listen_state(self.chk_prod_mode,"input_boolean.turn_on_ad_production_mode")
     #self.call_service("app/restart", app="BedHeat", namespace="appdaemon")

   def chk_prod_mode(self, entity, attribute, old, new, kwargs):
     if new=="off" and old=="on":
       self.log("Turning Appdaemon Production Mode OFF")
       self.call_service("production_mode/set", mode=False, namespace="appdaemon")
     if new=="on" and old=="off":
       self.log("Turning Appdaemon Production Mode ON")
       self.call_service("production_mode/set", mode=True, namespace="appdaemon")

Here’s my appdaemon.yaml file:

secrets: /config/secrets.yaml
logs:
  main_log:
    filename: /config/appdaemon/Logs/appdaemon.log
  access_log:
    filename: /config/appdaemon/Logs/appdaemonaccess.log
  error_log:
    filename: /config/appdaemon/Logs/appdaemonerr.log
appdaemon:
  latitude: redaction
  longitude: redaction
  elevation: 9
  time_zone: America/New_York
  app_dir: /config/appdaemon/apps
  plugins:
    HASS:
      type: hass
      ha_url: http://192.168.1.215:8123
      token: eyJ0eXAiOiJ......redacted
http:
  url: http://192.168.1.215:5050
api:
admin:
  title: AppDaemon
  stats_update: realtime

Note that the restart service call works without any issues.

Thanks for any insight you can provide!

Tom

I suggest opening a new topic for your question instead of posting it in this topic.

I can only guess, buy maybe you need to add production_mode: true to your appdaemon.yaml file for the service calls to work.

tom, if its possible to ask your questions on our discord server then i would highly appreciate that.

i just tested but i got the same problem. so lets ask @Odianosen25 how he uses it.
@Burningstone if that would work it would be a bug anyway. the service call should just work.

but another remark @eBoon
please try to avoid using old style app writing combined with new style appwriting.

old style is inherit from 1 plugin by using:

import appdaemon.plugins.hass.hassapi as hass
class Alexa_AD(hass.Hass):

    def initialize(self): 
        self.log("a")
        self.turn_on(entity)

in that case dont import adbase

new style:

import adbase as ad

class Broadlink_App(ad.ADBase):
  
    def initialize(self): 
        self.adbase = self.get_ad_api()
        self.hass = self.get_plugin_api("hass")
        self.adbase.log("a")
        self.hass.turn_on(entity)

there are a lot of new functions/options in AD 4, but they are mostly developed and tested for the new style apps. combining styles (inherit from plugin, and still import adbase and use it) is asking for trouble.

2 Likes

Yeah, you’re right (as always :stuck_out_tongue:). I was just making an uneducated guess.

hmm, i like to be always right, but i am still human :wink:
but it wouldnt be a bad try, and it would be possible that thats the reason the bug got unnoticed.
my other guess was that new style app was needed, but that gave the same error.

and the code has become to complicated so that i can do a quick lookup, to see if another namespace is needed

and then i saw why the error probably isnt noticed before:

dont use call_service.

but in stead just use the function that is created for it:

self.set_production_mode(True/False)

1 Like

@eBoon,

Strange this issue is happening. This works for me

def initialize(self): 
        self.adbase = self.get_ad_api()
        self.adbase.call_service("production_mode/set", mode=True, namespace="appdaemon")

Not sure why this is happening for you really

Yes that actually was imputed before the service call, so might just be the call_service side of things is quite new. Actually it is, one of the things that was added newly

Any plans on adding config validations? Similar to all the helper classes in HA.

There was discussions about that, but nothing concrete yet.

Its difficult to have it in AD, due to the flexibility on how AD can be used, unless standard stuffs.

But there is plan for using modules like voluptuous

Regards

That did it - working now!!

Thanks!