restart modem on failure and wildcard on tty

Change-Id: I7f802e2e44aa8618bafbc707d93ad5b2b6236a41
diff --git a/VERSION b/VERSION
index 844f6a9..d2b13eb 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.6.3
+0.6.4
diff --git a/edge-monitoring/agent_modem/config.json b/edge-monitoring/agent_modem/config.json
index 3a33d1d..7bfb02d 100644
--- a/edge-monitoring/agent_modem/config.json
+++ b/edge-monitoring/agent_modem/config.json
@@ -1,7 +1,7 @@
 {
     "edge_name": "ace-sample",
     "modem": {
-        "port": "/dev/ttyACM0",
+        "port": "/dev/ttyACM*",
         "baud": 115200,
         "ip_addr": "192.168.0.1"
     },
diff --git a/edge-monitoring/agent_modem/edge_monitoring_agent_modem.py b/edge-monitoring/agent_modem/edge_monitoring_agent_modem.py
index f669471..1d31474 100755
--- a/edge-monitoring/agent_modem/edge_monitoring_agent_modem.py
+++ b/edge-monitoring/agent_modem/edge_monitoring_agent_modem.py
@@ -54,7 +54,22 @@
         self.baudrate = baudrate
         self._response = None
 
+    def get_modem_port(self):
+        cmd = "ls " + CONF.modem.port
+        sp = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE, universal_newlines=True)
+        rc = sp.wait()
+        ret,err = sp.communicate()
+        if err != "" :
+            logging.error("unable to find serial port " + err)
+
+        ret = ret.replace(CONF.modem.port,"").strip()
+        logging.info("Modem.get_modem_port found " + ret)
+        return ret
+
     def connect(self):
+        self.port=self.get_modem_port()
+        logging.info("modem.connect Port: %s, BaudRate: %i",self.port,self.baudrate)
         self.serial = serial.Serial(
             port=self.port,
             baudrate=self.baudrate,
@@ -101,9 +116,9 @@
     # Disable radio fuction
     # "echo" works more stable than serial for this action
     try:
-        logging.debug("echo 'AT+CFUN=0' > " + CONF.modem.port)
+        logging.debug("echo 'AT+CFUN=0' > " + modem.port)
         subprocess.check_output(
-            "echo 'AT+CFUN=0' > " + CONF.modem.port, shell=True)
+            "echo 'AT+CFUN=0' > " + modem.port, shell=True)
     except subprocess.CalledProcessError as e:
         logging.error("Write 'AT+CFUN=0' failed")
         return State.error
@@ -126,9 +141,9 @@
     # Enable radio function
     # "echo" works more stable than serial for this action
     try:
-        logging.debug("echo 'AT+CFUN=1' > " + CONF.modem.port)
+        logging.debug("echo 'AT+CFUN=1' > " + modem.port)
         subprocess.check_output(
-            "echo 'AT+CFUN=1' > " + CONF.modem.port, shell=True)
+            "echo 'AT+CFUN=1' > " + modem.port, shell=True)
     except subprocess.CalledProcessError as e:
         logging.error("Write 'AT+CFUN=1' failed")
         return State.error
@@ -232,9 +247,11 @@
 
 def get_signal_quality(modem):
     success, result = modem.write('AT+CESQ')
+    logging.debug("get_signal_quality success %i result %s",success,result)
     if not success or 'CESQ: ' not in result:
         logging.error("Failed to get signal quality")
-        return { 'rsrq': 0, 'rsrp': 0 }
+
+        return {'rsrq':0, 'rsrp':0}
 
     logging.debug("%s", result)
     tmp_rsrq = result.split('CESQ:')[1].split(',')[4]
@@ -290,9 +307,12 @@
     report['signal_quality'] = signal_quality
 
     logging.info("Sending report %s", report)
+    global cycles
+    cycles += 1
+    logging.info("Number of cycles since modem restart %i",cycles)
     try:
         result = requests.post(CONF.report_url, json=report)
-    except requests.exceptions.ConnectionError:
+    except requests.exceptions.ConnectionError as e:
         logging.error("Failed to report for %s", e)
         pass
     try:
@@ -301,9 +321,34 @@
         logging.error("Failed to report for %s", e)
         pass
     time.sleep(CONF.report_interval)
+def reset_usb():
+    cmd = "/usr/sbin/uhubctl -a 0 -l 2" # -a 0 = action is shutdown -l 2 location = bus 2 on pi controls power to all hubs
+    ret = subprocess.call(cmd,shell=True)
+    logging.info("Shutting down usb hub 2 results %s" , ret)
+    time.sleep(10)# let power down process settle out
+    cmd = "/usr/sbin/uhubctl -a 1 -l 2" # -a 1 = action is start -l 2 location = bus 2 on pi controls power to all hubs
+    ret = subprocess.call(cmd,shell=True)
+    logging.info("Starting up usb hub 2 results %s" , ret)
+    time.sleep(10) #allow dbus to finish
+    global cycles
+    cycles = 0
+
 
 
 def main():
+    global cycles
+    cycles = 0
+    for ip in CONF.ips:
+        if not ip:
+            continue
+        try:
+            subprocess.check_output("sudo ip route replace {}/32 via {}".format(
+                ip, CONF.modem.ip_addr), shell=True)
+        except subprocess.CalledProcessError as e:
+            logging.error("Failed to add routes", e.returncode, e.output)
+            reset_usb()
+            sys.exit(1)
+
     modem = Modem(CONF.modem.port, CONF.modem.baud)
     try:
         modem.connect()
@@ -311,23 +356,13 @@
         logging.error("Failed to connect the modem for %s", e)
         sys.exit(1)
 
-    for ip in CONF.ips:
-        if not ip:
-            continue
-        try:
-            subprocess.check_output("sudo ip route replace {}/32 via {}".format(
-                ip, CONF.modem.ip_addr), shell=True)
-            logging.info("Added route for test address: %s", ip)
-        except subprocess.CalledProcessError as e:
-            logging.error("Failed to add routes %s", e.output)
-            sys.exit(1)
-
     while True:
         signal_quality = get_signal_quality(modem)
 
         cp_state = get_control_plane_state(modem)
         if cp_state is State.error:
             logging.error("Modem is in error state.")
+            reset_usb()
             sys.exit(1)
         if cp_state is State.disconnected:
             # Failed to attach, don't need to run other tests