コード例 #1
0
ファイル: interface.py プロジェクト: pratikpanchal22/birdbox
    def run(self):
        atSettings = {}
        atSettings['fp'] = getAudioBasePath() + self._audioFileName
        atSettings['vol'] = 100
        atSettings['repeat'] = False
        atSettings['tName'] = "AudioThread_id_" + str(self._id)
        audioThread = at(**atSettings)

        #Use Id to mark entry as active
        Models(Db(dbc.MYSQL_DB).connection()).push(
            ModelType.FOR_ID_SET_ACTIVE_UPDATE_TS, self._id)

        #Start audio thread
        audioThread.start()

        AudioDbInterface.candidateAudioThreads.append(audioThread)

        logger("_INFO_", "  Starting thread: ", audioThread.getName(),
               "  state=", audioThread.isAlive())

        #Wait for completion
        audioThread.join()

        #Use Id to mark entry as inactive
        Models(Db(dbc.MYSQL_DB).connection()).push(
            ModelType.FOR_ID_UNSET_ACTIVE, self._id)

        AudioDbInterface.candidateAudioThreads.remove(audioThread)

        logger("_INFO_", "  Thread ending: ", audioThread.getName(),
               "  state=", audioThread.isAlive())
        return
コード例 #2
0
 def __fetchModel(self):
     if (self._appSettingsId > 0):
         self._appSettings = Models(Db(dbc.MYSQL_DB).connection()).fetch(
             ModelType.APP_SETTINGS_FOR_ID, self._appSettingsId)
     else:
         self._appSettings = Models(Db(dbc.MYSQL_DB).connection()).fetch(
             ModelType.APP_SETTINGS)
     self._settingsJson = json.loads(self._appSettings[0][dbc.KEY_SETTINGS])
     return
コード例 #3
0
ファイル: app.py プロジェクト: pratikpanchal22/birdbox
def infoPage():    
    #Grab the id from url parameters
    id = request.args.get("id")
    #Fetch model
    data = Models(mysql.connection).fetch(ModelType.INFO_FOR_ID, id)

    #If the data returned is not exactly 1, go to home page
    if(len(data) != 1):
        return index()

    ts = str(int(time.time()))

    jsInclude = '<script src="/static/js/scripts.js?t='+ts+'"></script>'
    jsInclude += '<script src="/static/js/infoPageScripts.js?t='+ts+'"></script>'
    jsInclude += '<script src="https://kit.fontawesome.com/7daabcbab0.js" crossorigin="anonymous"></script>'
    cssInclude = '<link rel="stylesheet" href="static/css/styles.css?t='+ts+'">'

    templateData = {
        'jsInclude' : jsInclude,
        'cssInclude' : cssInclude
    }

    templateData.update(data[0])

    #Pass to template Data
    return render_template('infoPage.html', **templateData)
コード例 #4
0
ファイル: app.py プロジェクト: pratikpanchal22/birdbox
def combinatoricData():
    ts = str(int(time.time()))

    response = {
        "state":"unsuccessful",
        "ts": ts
    }
    
    location = request.args.get("landscape")
    r = int(request.args.get("channels"))
    logger("_INFO_", "location=", location)

    d = Models(mysql.connection).fetch(ModelType.LOCATION_INFO, location)

    logger("_INFO_", "d=", d)
    logger("_INFO_", "d[totalBirdSounds]=", d[0]['totalBirdSounds'])
    #combinations = nCr
    n = d[0]['totalBirdSounds']
    if(n>0 and r>0):
        combInt = math.factorial(n)/(math.factorial(n-r) * math.factorial(r))
        comb = '{:.0}'.format(math.factorial(n)/(math.factorial(n-r) * math.factorial(r)))
        logger("_INFO_", "Combinations: ", comb, " Probability=", str(100/combInt))

        landscapeSubData = "This landscape has " + str(d[0]["distinctBirds"]) + " unique birds, " + str(d[0]["totalBirdSounds"]) + " songs, calls and other birdsounds, and " + str(d[0]["landscapeSounds"]) + " ambient soundscapes."
        channelsSubData = "With this setting, the number of birdsounds combinations possible are " + '{:,}'.format(combInt)[:-2] + ". Or in other words, the probability of listening to the same combination is " + f"{Decimal(100/combInt):.4E}" +"%"
        
        response["state"] = "successful"
        response["landscapeSubData"] = landscapeSubData
        response["channelsSubData"] = channelsSubData

    return json.dumps(response)
コード例 #5
0
ファイル: app.py プロジェクト: pratikpanchal22/birdbox
def idData():
    ts = str(int(time.time()))
    
    t = request.args.get("t")
    comma_separated_ids = request.args.get("id")
    #ids = u.comma_separated_params_to_list(request.args.get("id"))
    #print ("\n\n############# ids: ",ids)
    #for id in ids:
    #    print ("id: ",id)

    #print("local ts=",ts," t=",t," diff=",int(ts)-int(t))

    jsonObj = {
        "state":"unknown",
        "ts":ts
    }

    if(int(ts) - int(t) > 2):
        #Request too old
        jsonObj["state"] = "request too old"
        print("Rejecting request because it is too old", jsonObj)
        return jsonify(jsonObj)

    entries = Models(mysql.connection).fetch(ModelType.METADATA_FOR_IDS, comma_separated_ids)
    print("\nConverting entries to JSON:")
    print(json.dumps(entries, cls=dte))

    if(len(entries)==0):
        jsonObj["state"] = "empty"
    else:
        jsonObj["state"] = "successful"
        jsonObj["data"] = json.dumps(entries, cls=dte)

    return json.dumps(jsonObj)
コード例 #6
0
ファイル: interface.py プロジェクト: pratikpanchal22/birdbox
    def terminate(self):
        logger("_INFO_", "Terminating continuous playback")

        #Cancel existing callback
        if (self._futureTerminationCallback != None):
            self._futureTerminationCallback.cancel()

        #Update the database
        queryFrag = "'$.continuousPlayback.enabled', False"
        Models(Db(dbc.MYSQL_DB).connection()).push(
            ModelType.UPDATE_APP_SETTINGS_IN_PLACE, str(queryFrag))

        self._rerun = False
        return
コード例 #7
0
ファイル: interface.py プロジェクト: pratikpanchal22/birdbox
def disableAmbientChannelAndUpdateSettings(ch):

    if (ch == 'ambientAudioChannel1'):
        queryFrag = "'$.continuousPlayback.ambience1', 'None'"
    elif (ch == 'ambientAudioChannel2'):
        queryFrag = "'$.continuousPlayback.ambience2', 'None'"
    else:
        logger("_INFO_", "Unsupported channel: ", ch)
        return

    #Update app settings in-place
    a = Models(Db(dbc.MYSQL_DB).connection()).push(
        ModelType.UPDATE_APP_SETTINGS_IN_PLACE, str(queryFrag))
    logger("_INFO_", "Settings updated inplace in database. Return: ", str(a))
    return
コード例 #8
0
ファイル: app.py プロジェクト: pratikpanchal22/birdbox
def onStage():
    ts = str(int(time.time()))
    
    t = request.args.get("t")

    #print("local ts=",ts," t=",t," diff=",int(ts)-int(t))

    jsonObj = {
        "state":"unknown",
        "ts":ts
    }

    if(int(ts) - int(t) > 2):
        #Request too old
        jsonObj["state"] = "request too old"
        print("Rejecting request because it is too old", jsonObj)
        return jsonify(jsonObj)

    refetch = True
    while refetch==True:
        entries = None
        entries = Models(mysql.connection).fetch(ModelType.ACTIVE_ENTRIES)
        entries = [e['id'] for e in entries]
        logger("_INFO_", "\nfetchActiveEntries: ", json.dumps(entries))
        if(len(entries)==0):
            jsonObj["state"] = "empty"
            refetch = False
        else:
            purged = interface.purgeDeadEntries(60)
            print("Entries purged: ", purged)
            if(purged == 0):
                refetch = False
                jsonObj["state"] = "successful"
                jsonObj["data"] = json.dumps(entries)
            else:
                refetch = True

    return json.dumps(jsonObj)
コード例 #9
0
ファイル: interface.py プロジェクト: pratikpanchal22/birdbox
def getCandidateAudioFiles(appSettings, **kwargs):
    #print("\n--> ",inspect.stack()[0][3], " CALLED BY ",inspect.stack()[1][3])

    #2. TODO: Verify that required time has passed since last playback

    try:
        requestedChannels = kwargs['requestedChannels']
    except:
        requestedChannels = 1

    #Purge dead entries
    #Fetch
    activeEntries = Models(Db(dbc.MYSQL_DB).connection()).fetch(
        ModelType.ACTIVE_ENTRIES)
    activeEntries = [d[dbc.KEY_ID] for d in activeEntries]

    #3. Verify that number of active entries don't exceed maximum allowed
    if (len(activeEntries) > 0):
        purged = purgeDeadEntries(60)
        if (purged > 0):
            logger("_INFO_", purged, "Entries purged")
            activeEntries = Models(Db(dbc.MYSQL_DB).connection()).fetch(
                ModelType.ACTIVE_ENTRIES)

    logger("_INFO_", "Active entries:", activeEntries)
    logger("_INFO_", "Active/maxAllowed=", len(activeEntries), "/",
           appSettings.maxNumberOfAllowedSimultaneousChannels())
    if (len(activeEntries) >=
            appSettings.maxNumberOfAllowedSimultaneousChannels()):
        logger("_INFO_", "Channels saturated. Ignoring trigger. Exiting\n")
        return []

    #4. Compute number of channels to implement
    if (requestedChannels == 1):
        numberOfChannels = 1
    elif (requestedChannels > 1):
        emptyChannels = appSettings.maxNumberOfAllowedSimultaneousChannels(
        ) - len(activeEntries)
        if (requestedChannels > emptyChannels):
            numberOfChannels = emptyChannels
        else:
            numberOfChannels = requestedChannels

        if (randomizeNumberOfChannels):
            numberOfChannels = random.randint(1, requestedChannels)
    else:
        logger("_ERROR_", "Unsupported requested number of channels:",
               str(requestedChannels))
        return []

    #Scope:
    # (1) Fetch all sorted by last_updated asc
    data = Models(Db(dbc.MYSQL_DB).connection()).fetch(
        ModelType.IDS_NAMES_AUDIOFILE_SORTED_BY_LAST_UPDATED_OLDEST_FIRST)
    # (2) Select one t random from top 75% of that list
    #for d in data:
    #    print("New line")
    #    print(d[0])
    #    print(d[1])

    logger("_INFO_", "Total data rows: ", len(data))
    #print(type(data))
    #for d in data:
    #    print(type(d))
    #print(data)
    #print("\nJSON dumps:",json.dumps(data))

    allIds = [d[dbc.KEY_ID] for d in data]
    logger("_INFO_", allIds)
    eligibleLength = int(0.75 * len(data))
    candidates = []

    #Choose first at random
    candidates.append(data[random.randint(0, eligibleLength - 1)])
    logger("_INFO_", "CHOOSING 1st candidate:")
    logger(
        "_INFO_",
        "{:>4.4} {:32.32} {}".format(str(candidates[0][dbc.KEY_ID]),
                                     candidates[0][dbc.KEY_NAME],
                                     candidates[0][dbc.KEY_AUDIO_FILE]))
    data.remove(candidates[0])

    #Remove last 25%
    indicesToRemove = len(data) - eligibleLength
    for i in range(0, indicesToRemove):
        data.remove(data[len(data) - 1])

    logger("_INFO_", "Total number of channels to implement: ",
           numberOfChannels)

    if (numberOfChannels > 1):
        speciesConstrainedSet = []
        logger("INFO_", "Limit to same species: ",
               appSettings.isBirdChoiceLimitedToSameSpecies())
        if (appSettings.isBirdChoiceLimitedToSameSpecies()):
            for d in data:
                if (d == candidates[0]):
                    print(d, " :Already exists. Skipping")
                    #data.remove(candidates[0])
                    continue
                elif (d[dbc.KEY_NAME] == candidates[0][dbc.KEY_NAME]):
                    speciesConstrainedSet.append(d)
            data = speciesConstrainedSet

        logger("_INFO_", "Curated candidate data set: size=", len(data))
        for element in data:
            logger(
                "_INFO_",
                "{:>4.4} {:32.32} {}".format(str(element[dbc.KEY_ID]),
                                             element[dbc.KEY_NAME],
                                             element[dbc.KEY_AUDIO_FILE]))

        if (numberOfChannels >= len(data)):
            logger(
                "_INFO_", "Number of channels to implement " +
                numberOfChannels + " is more or equal to data set at hand ",
                len(data))
            for d in data:
                candidates.append(d)
        else:
            for i in range(0, numberOfChannels - 1):
                logger("_INFO_", "\nSelecting For channel ", i + 2)
                randomlyChosenRowIdx = random.randint(0, len(data) - 1)
                logger(
                    "_INFO_", "Size of data:", len(data), "  Chosen idx:",
                    randomlyChosenRowIdx, "id={} {} {}".format(
                        str(data[randomlyChosenRowIdx][dbc.KEY_ID]),
                        data[randomlyChosenRowIdx][dbc.KEY_NAME],
                        data[randomlyChosenRowIdx][dbc.KEY_AUDIO_FILE]))
                candidates.append(data[randomlyChosenRowIdx])
                #remove that row to avoid duplication
                data.remove(data[randomlyChosenRowIdx])

    #logger("_INFO_", "Final candidate list: ")
    #candidateAudioFiles = []
    #for c in candidates:
    #    print (c)
    #    candidateAudioFiles.append(c[1])
    return candidates
コード例 #10
0
ファイル: interface.py プロジェクト: pratikpanchal22/birdbox
def processUpstageSoundscape(ch, **kwargs):
    try:
        if (kwargs['terminate']):
            if (kwargs.get("terminate") == True):
                terminateSoundscapeAudioThread(ch)
        return
    except KeyError:
        logger("_INFO_", ch, " won't be terminated")

    atSettings = {}
    for key, value in kwargs.items():
        if (key == 'name'):
            if (value == 'None'):
                terminateSoundscapeAudioThread(ch)
                return
            else:
                d = Models(Db(dbc.MYSQL_DB).connection()).fetch(
                    ModelType.ID_FILE_FOR_NAME, value)[0]
                atSettings['fp'] = getAudioBasePath() + d[dbc.KEY_AUDIO_FILE]
        elif (key == 'endTime'):
            atSettings['terminateAt'] = value
        elif (key == 'vol'):
            atSettings['vol'] = value
        else:
            print("Unsupported key/value pair: ", str(key), ":", str(value))

    if (globals()[ch] == None or globals()[ch].isAlive() == False):
        #start new
        globals()[ch] = at(**atSettings)
        globals()[ch].start()

        #Update database if required
        logger("_INFO_", "audiothread started and waiting for completion")

        #Wait for completion
        globals()[ch].join()

        #Update database: appSettings
        logger("_INFO_",
               "Update appSettings here to reflect thread termination")
        disableAmbientChannelAndUpdateSettings(ch)
    else:
        #update existing
        for k, v in atSettings.items():
            if (k == 'fp'):
                try:
                    globals()[ch].changeFile(v)
                except:
                    logger("_ERROR_", "Fatal error: Could not change ", k,
                           "on", ch)
            elif (k == 'vol'):
                try:
                    globals()[ch].changeVolume(v)
                except:
                    logger("_ERROR_", "Fatal error: Could not change ", k,
                           "on", ch)
            elif (k == 'terminateAt'):
                try:
                    globals()[ch].setFutureTerminationTime(v)
                except:
                    logger("_ERROR_", "Fatal error: Could not change ", k,
                           "on", ch)
            else:
                print("Unsupported AT key/value pair: ", str(k), ":", str(v))

    return
コード例 #11
0
ファイル: interface.py プロジェクト: pratikpanchal22/birdbox
def purgeDeadEntries(seconds):
    return int(
        Models(Db(dbc.MYSQL_DB).connection()).push(
            ModelType.UNSET_ACTIVE_FOR_DEAD_ENTRIES, seconds))
コード例 #12
0
ファイル: app.py プロジェクト: pratikpanchal22/birdbox
def settings():
    ts = str(int(time.time()))

    jsInclude = '<script src="/static/js/scripts.js?t='+ts+'"></script>'
    jsInclude += '<script src="/static/js/settings.js?t='+ts+'"></script>'
    jsInclude += '<script src="https://kit.fontawesome.com/7daabcbab0.js" crossorigin="anonymous"></script>'
    cssInclude = '<link rel="stylesheet" href="static/css/styles.css?t='+ts+'">'
    cssInclude += '<link rel="stylesheet" href="static/css/settings.css?t='+ts+'">'

    templateData = {
        'jsInclude' : jsInclude,
        'cssInclude' : cssInclude
    }

    a = AppSettings()
    d = a.getSettings()
    #print("Type of d: ", type(d))

    #print(settings['settings']['continuousPlayback']['enabled'])
    #print(d['landscape'])
    #print(d['continuousPlayback']['enabled'])
    #print(d['continuousPlayback']['endTime'])
    #print(d['continuousPlayback']['ambience1'])
    #print(d['continuousPlayback']['ambience2'])
    #print(d['motionTriggers']['enabled'])
    #print(d['motionTriggers']['frequency'])
    #print(d['symphony']['enabled'])
    #print(d['symphony']['maximum'])
    #print(d['symphony']['limitToSameType'])
    #print(d['silentPeriod']['enabled'])
    #print(d['silentPeriod']['startTime'])
    #print(d['silentPeriod']['endTime'])
    #print(d['volume'])

    #Fetch options for 'landscape'
    landscapeLocations = Models(mysql.connection).fetch(ModelType.LIST_OF_LOCATIONS)
    
    #Fetch options for 'ambience'
    soundscapes = Models(mysql.connection).fetch(ModelType.LIST_OF_SOUNDSCAPES_FOR_LOC, d['landscape'])
    
    #Insert an empty item as an option for user to select
    emptyItem = {'name' : 'None'}
    soundscapes.insert(0, emptyItem)

    #Prepopulate endTime if continuousPlayback is disabled
    if(d['continuousPlayback']['enabled'] == False):
        defaultEndTime = datetime.datetime.now() + datetime.timedelta(minutes = 30) 
        d['continuousPlayback']['endTime'] = defaultEndTime.strftime("%H:%M")

    settingsTemplateData = {
        'last_updated' : a.getLastUpdated(),
        
        'landscape' : d['landscape'],
        'landscapeLocations' : landscapeLocations,

        'cbEnabled' : d['continuousPlayback']['enabled'],
        'birdsEnabled' : d['continuousPlayback']['birdsEnabled'],
        'ambienceEnabled' : d['continuousPlayback']['upStageEnabled'],
        'ambience1' : d['continuousPlayback']['ambience1'],
        'amb1Vol' : d['continuousPlayback']['amb1Vol'],
        'ambience2' : d['continuousPlayback']['ambience2'],
        'amb2Vol' : d['continuousPlayback']['amb2Vol'],
        'cbEndTime' : d['continuousPlayback']['endTime'],
        'ambientLocations' : soundscapes,
        
        'mtEnabled' : d['motionTriggers']['enabled'],
        'mtPeriod' : d['motionTriggers']['frequency'],
        'symphony' : d['symphony']['enabled'],
        'symMaxBirds' : d['symphony']['maximum'],
        'symLimitToSame' : d['symphony']['limitToSameType'],
        'silentPeriod' : d['silentPeriod']['enabled'],
        'spStartTime' : d['silentPeriod']['startTime'],
        'spEndTime' : d['silentPeriod']['endTime'],
        #'volume' : d['volume']
        'volume' : av.getCurrentVolume()
    }
    
    templateData.update(settingsTemplateData)
    return render_template('settings.html', **templateData)    
コード例 #13
0
def iterate():
    print("\nNew Iteration:", datetime.now())

    response = Models().fetch(ModelType.NODE_TO_QUERY)
    id = response[0][0]
    nodeIp = response[0][1]
    nodeId = response[0][2]

    lastRecord = Models().fetch(ModelType.LAST_NODE_TELEMETRY_RECORD, nodeId)

    apiIdToFetch = "Identity"
    if (lastRecord[0][3] == 'System statistics'):
        apiIdToFetch = "Identity"
    elif (lastRecord[0][3] == 'Identity'):
        apiIdToFetch = "System statistics"
    else:
        apiIdToFetch = "Identity"

    api = Models().fetch(ModelType.FETCH_ENDPOINT_FOR_API_ID, apiIdToFetch)
    api_id = api[0][0]
    ep = api[0][1]

    #request
    url = 'http://' + nodeIp + ep
    print("-> URL to GET: ", url)

    jsonResponse = '{}'
    http_status_code = -1
    status_str = "SUCCESS"

    try:
        td = requests.get(url, timeout=10)
        jsonResponse = td.text
        http_status_code = td.status_code

        print("-> Response HTTP status code:", http_status_code)

        if (http_status_code != 200):
            status_str = "FAIL"
            print("-> Response: ", jsonResponse)

        if (nodeId != td.json()['node']):
            status_str = "Mismatched NodeId"

    except requests.exceptions.Timeout as e:
        print("-> Exception: Timeout: ", e)
        status_str = str(e)
    except requests.exceptions.RequestsWarning as e:
        print("-> Exception: RequestsWarning: ", e)
        status_str = str(e)
    except requests.exceptions.RetryError as e:
        print("-> Exception: RetryError: ", e)
        status_str = str(e)
    except requests.exceptions.RequestException as e:
        print("-> Exception: RequestException: ", e)
        status_str = str(e)

    #Add telemetry data
    rowsAdded = Models().push(ModelType.TELEMETRY_DATA, nodeId, api_id,
                              http_status_code, jsonResponse, status_str)
    print("-> Number of telemetry data-rows added successfully:", rowsAdded)

    if (rowsAdded != 1):
        print(" ERROR! Expected 1. Received:", rowsAdded)

    #Update node_list with ts
    rowsAdded = Models().push(ModelType.UPDATE_TIMESTAMP_FOR_ID, id)
    print("-> Timestamp updated for node", nodeId, "| Rows updated:",
          rowsAdded)

    if (rowsAdded != 1):
        print(" ERROR! Expected 1. Received:", rowsAdded)

    numberOfNodesToQuery = Models().fetch(
        ModelType.NUMBER_OF_ACTIVE_QUERIES)[0][0]
    nodeQueryPeriodicity = 120  #seconds - TODO: fetch from database
    secondsToPause = nodeQueryPeriodicity / numberOfNodesToQuery

    print("-> Next thread will run in ", secondsToPause, " seconds")

    nextThread = threading.Timer(secondsToPause, iterate)
    nextThread.start()
コード例 #14
0
 def save(self, jsonStr):
     Models(Db(dbc.MYSQL_DB).connection()).push(ModelType.APP_SETTINGS,
                                                jsonStr)
     self.refresh()
     return
コード例 #15
0
def main():
    ts = str(int(time.time()))

    jsInclude = '<script src="/static/js/scripts.js?t='+ts+'"></script>'
    jsInclude += '<script src="https://kit.fontawesome.com/7daabcbab0.js" crossorigin="anonymous"></script>'
    
    cssInclude = '<link rel="stylesheet" href="static/css/styles.css?t='+ts+'">'

    results = Models(mysql.get_db()).fetch(ModelType.NODE_LIST)
    print("Type of results: ", type(results))

    newResults = ()
    nodeArrayJson = []
    for var in results:

        nodeJson = {
            "nodeId" : var[3],
            "name" : var[4],
            "status" : var[6],
            "last_updated": var[2],
            "last_seen": passed_time_string_for_past_dto(var[2])
        }
        
        r = Models(mysql.get_db()).fetch(ModelType.NODE_TELEMETRY_LATEST_RECORD_FOR_NODE_ID, 
                                        nodeJson['nodeId'], 'System statistics')[0]

        nodeJson["apiIdKey"] = r[3]
        nodeJson["apiIdValue"] = r[5]

        s = Models(mysql.get_db()).fetch(ModelType.NODE_TELEMETRY_LATEST_RECORD_FOR_NODE_ID, 
                                nodeJson['nodeId'], 'Identity')

        try:
            identityJson = json.loads(s[0][5])
            nodeJson["firmware"] = identityJson['current']['version']
            nodeJson["firmware build"] = identityJson['current']['build']
            nodeJson["board"] = identityJson['current']['board']
            nodeJson["First boot"] = identityJson['current']['fBoot']
        except:
            nodeJson["firmware"] = "Unavailabe"


        nodeArrayJson.append(nodeJson)

        element = var + r

        eList = list(element) #[*element]
        ctr=0
        for i in eList:
            print(ctr, ":::", i)
            
            if(ctr == 12):
                try:
                    jsonE = json.loads(i)
                except:
                    jsonE = {}
                    print("Unable to convert to json")

                try:
                    print("JSON: ", jsonE['ip'])
                    itemIp = jsonE['ip']
                except:
                    itemIp = "IPV4 unknown"
                    print("ip not found")

                try:    
                    print("JSON: ", jsonE['session']['uptime'])
                    itemUptime = "Up since "+jsonE['session']['uptime']
                except:
                    itemUptime = "Uptime unknown"
                    print("uptime not found")

                try:
                    print("JSON: ", jsonE['calendarEvents'])
                    itemCe = str(jsonE['calendarEvents']) + " calendar events"
                except:
                    itemCe = "Calendar events unknown"
                    print("calendarEvents not found")

                try:
                    print("JSON: ", jsonE['scheduledEvents'])
                    itemSe = str(jsonE['scheduledEvents']) + " scheduled events"
                except:
                    itemSe = "Scheduled events unknown"
                    print("scheduledEvents not found")

                try:
                    print("JSON: ", jsonE['temperature'])
                    if(jsonE['temperature'] == -100):
                        itemTe = "No onboard Temp. sensor"
                    else:
                        itemTe = "Onboard temp:" + str(jsonE['temperature'])
                except:
                    itemTe = "Temp. unknown"
                    print("temp not found")

                tupToAdd = (itemIp, itemUptime, itemCe, itemSe, itemTe, )
                element = element + tupToAdd
            
            ctr = ctr+1

        print ("\nElement: ", element, "\n")
        newResults = newResults + (element,)


        print("\n\n")

    print("\n\n\nNew Results: ", newResults)
    print("\n\n********************\nConstructed JSON: ", json.dumps(nodeArrayJson, cls=dte, indent=4, sort_keys=False))

    print("\n\nNodeArrayJson size: ", len(nodeArrayJson))

    for nr in newResults:
        ctx = 0
        for i in nr:
            print(ctx," >>> ", i)
            ctx=ctx+1

    templateData = {
        'jsInclude' : jsInclude,
        'cssInclude' : cssInclude
    }
    return render_template('index.html', **templateData, data=newResults)