Repository: AppDaemon/appdaemon

Issue:
TypeError: a bytes-like object is required, not 'str'
When I build and run (`docker build -t appdaemon:dev . && docker run appdaemon:dev`) the `dev` branch, the app exits with errors.

```
2021-02-21 10:25:51.952206 INFO AppDaemon: AppDaemon Version 4.0.6 starting
2021-02-21 10:25:51.953718 INFO AppDaemon: Python version is 3.8.8
2021-02-21 10:25:51.953840 INFO AppDaemon: Configuration read from: /conf/appdaemon.yaml
2021-02-21 10:25:51.954030 INFO AppDaemon: Added log: AppDaemon
2021-02-21 10:25:51.954185 INFO AppDaemon: Added log: Error
2021-02-21 10:25:51.954361 INFO AppDaemon: Added log: Access
2021-02-21 10:25:51.954522 INFO AppDaemon: Added log: Diag
2021-02-21 10:25:52.012170 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2021-02-21 10:25:52.163496 INFO HASS: HASS Plugin Initializing
2021-02-21 10:25:52.187159 INFO HASS: HASS Plugin initialization complete
2021-02-21 10:25:52.187854 INFO AppDaemon: Initializing HTTP
2021-02-21 10:25:52.188573 INFO AppDaemon: Using 'ws' for event stream
2021-02-21 10:25:52.194850 WARNING AppDaemon: ------------------------------------------------------------
2021-02-21 10:25:52.195216 WARNING AppDaemon: Unexpected error in HTTP module
2021-02-21 10:25:52.195461 WARNING AppDaemon: ------------------------------------------------------------
2021-02-21 10:25:52.210179 WARNING AppDaemon: Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/appdaemon/http.py", line 171, in __init__
    net = url.netloc.split(":")
TypeError: a bytes-like object is required, not 'str'
...
...
...
2021-02-21 10:25:52.454334 WARNING AppDaemon: ------------------------------------------------------------
2021-02-21 10:25:52.455067 INFO AppDaemon: Previous message repeated 1 times
2021-02-21 10:25:52.455230 WARNING AppDaemon: Unexpected error during process_event()
2021-02-21 10:25:52.455544 WARNING AppDaemon: ------------------------------------------------------------
2021-02-21 10:25:52.455861 WARNING AppDaemon: Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/appdaemon/events.py", line 235, in process_event
    await self.AD.http.stream_update(namespace, mydata)
  File "/usr/local/lib/python3.8/site-packages/appdaemon/http.py", line 699, in stream_update
    self.AD.thread_async.call_async_no_wait(self.stream.process_event, data)
AttributeError: 'HTTP' object has no attribute 'stream'

2021-02-21 10:25:52.456080 WARNING AppDaemon: ------------------------------------------------------------
2021-02-21 10:25:52.462482 WARNING AppDaemon: ------------------------------------------------------------
2021-02-21 10:25:52.462707 WARNING AppDaemon: Unexpected error during run()
2021-02-21 10:25:52.462910 WARNING AppDaemon: ------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/appdaemon/__main__.py", line 149, in run
    loop.run_until_complete(asyncio.gather(*pending))
  File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.8/site-packages/appdaemon/admin_loop.py", line 18, in loop
    if self.AD.http.stats_update != "none" and self.AD.sched is not None:
AttributeError: 'HTTP' object has no attribute 'stats_update'
2021-02-21 10:25:52.467563 INFO AppDaemon: Previous message repeated 1 times
2021-02-21 10:25:52.468898 INFO AppDaemon: AppDaemon Exited
```



Discussion:
@wernerhp,

Did you configure the `http` component with your local IP address and port there?

Like this
```
http:
  url: http://192.168.xxx.xxx:5050
  password: !secret password
```
Ah, no I didn't.  I'll update the diff to check for this and output a friendlier error message to direct people to configure `url` in `appdaemon.yaml`
> output a friendlier error message to direct people to configure url in appdaemon.yaml

Yeah that's a good point

Resolving patch:
diff --git a/appdaemon/http.py b/appdaemon/http.py
--- a/appdaemon/http.py
+++ b/appdaemon/http.py
@@ -121,32 +121,19 @@ def __init__(self, ad: AppDaemon, loop, logging, appdaemon, dashboard, admin, ap
         self.template_dir = os.path.join(os.path.dirname(__file__), "assets", "templates")
 
         self.password = None
-        self._process_arg("password", http)
-
         self.valid_tokens = []
-        self._process_arg("tokens", http)
-
         self.url = None
-        self._process_arg("url", http)
-
         self.work_factor = 12
-        self._process_arg("work_factor", http)
-
         self.ssl_certificate = None
-        self._process_arg("ssl_certificate", http)
-
         self.ssl_key = None
-        self._process_arg("ssl_key", http)
-
         self.transport = "ws"
-        self._process_arg("transport", http)
-        self.logger.info("Using '%s' for event stream", self.transport)
 
         self.config_dir = None
         self._process_arg("config_dir", dashboard)
 
         self.static_dirs = {}
-        self._process_arg("static_dirs", http)
+
+        self._process_http(http)
 
         self.stopping = False
 
@@ -334,6 +321,25 @@ def __init__(self, ad: AppDaemon, loop, logging, appdaemon, dashboard, admin, ap
             self.logger.warning(traceback.format_exc())
             self.logger.warning("-" * 60)
 
+    def _process_http(self, http):
+        self._process_arg("password", http)
+        self._process_arg("tokens", http)
+        self._process_arg("work_factor", http)
+        self._process_arg("ssl_certificate", http)
+        self._process_arg("ssl_key", http)
+
+        self._process_arg("url", http)
+        if not self.url:
+            self.logger.warning(
+                "'{arg}' is '{value}'. Please configure appdaemon.yaml".format(arg="url", value=self.url)
+            )
+            exit(0)
+
+        self._process_arg("transport", http)
+        self.logger.info("Using '%s' for event stream", self.transport)
+
+        self._process_arg("static_dirs", http)
+
     async def start_server(self):
 
         self.logger.info("Running on port %s", self.port)


Test patch: