def update_api():
    """
    Function update_api , check if api are updates by using config file 
    """
    with open('config.json', 'r') as config_file:
        config_data = json.load(config_file)

    update_date = config_data["updates_api"][0]["last_update_time"]

    # If the api never was updated
    if update_date == "empty":
        news_filter.get_news()
        weather_update.get_weather()
        uk_covid_19.local_covid_data()
        config_data["updates"][0]["last_update_time"] = current_time

    else:
        # If the update date is expired ( more than 1 hour)
        if date_to_seconds(current_time) - date_to_seconds(
                update_date) >= 3600:
            news_filter.get_news()
            weather_update.get_weather()
            uk_covid_19.local_covid_data()
            config_data["updates"][0]["last_update_time"] = current_time
    with open('config.json', 'w') as config_file:
        json.dump(config_data, config_file)
Exemple #2
0
def make_notifications() -> None:
    '''
    Returns
    -------
    None
        This function calls on the news_filter and weather_update modules to
        collect the data form the relevant API's. It then unpacks them an
        appends them to the NOTIFICATIONS list for rendering.'''
    global NOTIFICATIONS
    NOTIFICATIONS = []
    api = Cov19API(filters=covid_data["nationally"], structure=covid_data["cases_and_deaths"])
    data = api.get_json()['data'][0]
    NOTIFICATIONS.append({'title': 'Covid Data',\
                          'content': Markup(
        f'<p style="text-align:left;">The COVID data for the\
        {data["areaName"]} as of {data["Date"]} is:\
        <br />Cases:\
        <br />&emsp;Total Cases: {str(data["cases"]["cumCasesByPublishDate"])}\
        <br />&emsp;New Cases: {str(data["cases"]["newCasesByPublishDate"])}\
        <br />Deaths:\
        <br />&emsp;Total Deaths: {str(data["deaths"]["cumDeaths28DaysByPublishDate"])}\
        <br />&emsp;New Deaths: {str(data["deaths"]["newDeaths28DaysByPublishDate"])}</p>')})
    NOTIFICATIONS.append({'title':'Weather',\
                          'content':Markup(get_weather(location['city'], API_keys['weather']))})
    NOTIFICATIONS.append({'title':'Headlines',\
                          'content':Markup(get_news(location['country'], API_keys['news'], True))})
    for notification in get_news(location['country'], API_keys['news']):
        NOTIFICATIONS.append(notification)
    logging.info('Notifications have been reloaded.')
Exemple #3
0
def announce_weather_and_news(announcement):
    """
    This function says out loud the content of the alarm that is expected to
    say also the weather and the news. It also says out loud the weather and the news.
    """

    logging.info("Alarm with news and weather has been said")
    try:
        engine.endLoop()
    except:
        logging.error('PyTTSx3 Endloop error')

    engine.say(announcement + get_weather() + get_news())
    engine.runAndWait()
Exemple #4
0
def print_news():
    """
    This function adds every six hours new weather, news and cases notifications
    into the notifications list that will be later displayed on the web server.
    """

    news_function = get_news()
    weather_funtion = get_weather()
    cases_function = get_cases()
    notifications.append({
        'title': current_time() + " - Weather",
        'content': weather_funtion
    })
    notifications.append({
        'title': current_time() + " - Top news",
        'content': news_function
    })
    notifications.append({
        'title': current_time() + " - Cases",
        'content': cases_function
    })
    logging.info("Notifications added to notifications list")
    s.enter(6 * 3600, 5, print_news, [])
Exemple #5
0
def run_alarm(alarm_label: str, news: bool = False, weather: bool = False) -> None:
    '''
    When an alarm is run we set off a noise aswell as showing
    any updates we need in news or weather
    '''

    text_to_read = []
    title = ""
    alarm_active = False

    # Find the alarm in the ALARMS list and remove it
    for alarm in ALARMS:
        if alarm['title'] == alarm_label:
            ALARMS.remove(alarm)
            alarm_active = True
            continue

    # If we can't find the alarm then return an error
    if not alarm_active:
        # Return error to log only, error alarm doesn't exist
        write_to_log(
            "ERROR TECH - No alarm found", False)
        return index

    write_to_log(
        "ALARM - Alarm: " + alarm_label + " has rung")
    # Add the alarm too the notifcation pannel
    title = "Alarm - " + alarm_label
    NOTIFICATIONS.append({"title": title, "content": (
        "Alarm " + alarm_label + " has rung")})

    # Add the alarm to the text to speech list
    text_to_read.append(("Alarm " + alarm_label + " has rung!"))

    # If news is enabled show the news and if Covid brief enabled show this too
    if news:
        # Same logic as the earlier brieifing just adds
        # the content too the text too speech
        text_to_read.append("News Update")

        # Make sure to still run if an api error is caught
        try:
            news_update, covid_update = get_news(
                CURRENT_COUNTRY, NEWS_KEY, NEWS_PROVIDER_PREFERENCES)
        except ValueError as e:
            message = news_update, covid_update = get_news(
                CURRENT_COUNTRY, NEWS_KEY, NEWS_PROVIDER_PREFERENCES)
            write_to_log(message)
            text_to_read.append(message)
            # Read out all loaded text so far
            tts_request(text_to_read)
            LOGGED_ERRORS.append(
                message)
            NOTIFICATIONS.append(
                {"title": ("Error - UID:" + str(len(LOGGED_ERRORS))), "content": message})
            # Save the NOTIFICATIONS and the removed alarm too the config
            write_config()
            return index

        for article in news_update:
            title = "News Update - " + \
                str(datetime.now().strftime("%d/%m/%Y %H:%M")) +\
                " - Story " + str(news_update.index(article) + 1)

            NOTIFICATIONS.append({"title": title, "content": article})

            text_to_read.append(article)

        if COVID_BRIEF:
            text_to_read.append("COVID-19 Update")

            # Make sure to run through even if the api is down or we have wrong information
            try:
                total_cases, cases_today = get_covid_19_cases(CURRENT_CITY)
            except ValueError as e:
                message = get_covid_19_cases(CURRENT_CITY)
                write_to_log(message)
                text_to_read.append(message)
                # Read out all loaded text so far
                tts_request(text_to_read)
                LOGGED_ERRORS.append(
                    message)
                NOTIFICATIONS.append(
                    {"title": ("Error - UID:" + str(len(LOGGED_ERRORS))), "content": message})
                # Save the NOTIFICATIONS and the removed alarm too the config
                write_config()
                return index

            message = "Covid-19 cases today in " + CURRENT_CITY + " " + \
                str(cases_today) + " giving a cumulative total of " + \
                str(total_cases) + " in " + CURRENT_CITY
            text_to_read.append(message)

            NOTIFICATIONS.append({"title": "COVID Statistics Update - " + str(
                datetime.now().strftime("%d/%m/%Y %H:%M")), "content": message})

            for covid_article in covid_update:
                title = "COVID News Update - " + \
                    str(datetime.now().strftime("%d/%m/%Y %H:%M")) +\
                    " - Story " + str(covid_update.index(covid_article) + 1)

                NOTIFICATIONS.append(
                    {"title": title, "content": covid_article})

                text_to_read.append(covid_article)

    # If weather brief is on then display the weather too
    if weather:
        # Same logic as the earlier brieifing just adds
        # the content too the text too speech
        text_to_read.append("Weather Update")

        # We make sure that there is a correct api key or city set otherwise we call an error
        try:
            current_temperature, current_pressure, current_humidiy, \
                weather_description = get_weather(CURRENT_CITY, WEATHER_KEY)
        except ValueError as e:
            message = get_weather(CURRENT_CITY, WEATHER_KEY)
            write_to_log(message)
            LOGGED_ERRORS.append(
                message)
            text_to_read.append(message)
            # Read out all loaded text so far
            tts_request(text_to_read)
            NOTIFICATIONS.append(
                {"title": ("Error - UID:" + str(len(LOGGED_ERRORS))), "content": message})
            # Save the NOTIFICATIONS and the removed alarm too the config
            write_config()
            return index

        NOTIFICATIONS.append(
            {"title": ("Weather Update - " +
                       str(datetime.now().strftime("%d/%m/%Y %H:%M"))),
             "content": ("Temperature (in degrees): " +
                         str(int(current_temperature) - 273) +
                         "\n | Atmospheric pressure (in hPa unit): " +
                         str(current_pressure) +
                         "\n | Humidity (as a percentage): " +
                         str(current_humidiy) +
                         "\n | Current weather: " +
                         str(weather_description))})
        text_to_read.append(("Temperature (in degrees) | " +
                             str(int(current_temperature) - 273) +
                             "\n | Atmospheric pressure (in hPa unit) | " +
                             str(current_pressure) +
                             "\n | Humidity (as a percentage) | " +
                             str(current_humidiy) +
                             "\n | Current weather | " +
                             str(weather_description)))

    # Save the NOTIFICATIONS and the removed alarm too the config
    write_config()

    # Read out the alarm aswell as any annoucements we added
    tts_request(text_to_read)

    # Refresh the main page
    return index
Exemple #6
0
def run_briefing(time_select: str, date_time) -> None:
    '''
    When a briefing time is reched we get the current news stories
    and weather aswell as covid-19 stories if this enabled by the
    user and display them silently in the NOTIFICATIONS
    '''

    # Load in the news and covid stories from the news api
    try:
        news_update, covid_update = get_news(
            CURRENT_COUNTRY, NEWS_KEY, NEWS_PROVIDER_PREFERENCES)
    except ValueError as e:
        message = get_news(
            CURRENT_COUNTRY, NEWS_KEY, NEWS_PROVIDER_PREFERENCES)
        write_to_log(message)
        LOGGED_ERRORS.append(
            message)
        NOTIFICATIONS.append(
            {"title": ("Error - UID:" + str(len(LOGGED_ERRORS))), "content": message})
        # Save the NOTIFICATIONS and the removed alarm too the config
        write_config()
        return index

    # Loop through all the news stories
    for article in news_update:
        # Add the news story as content along with a custom title
        # (effectively a UID for the notification) to the notification pannel
        title = "News Update - " + \
                str(datetime.now().strftime("%d/%m/%Y %H:%M")) +\
            " - Story " + str(news_update.index(article) + 1)
        NOTIFICATIONS.append({"title": title, "content": article})

    # If the user has enabled Covid-19 updates in their config (On by default)
    if COVID_BRIEF:

        # Make sure to run through even if the api is down or we have wrong information
        try:
            # Load in the daily covid cases for the current/nearest city
            total_cases, cases_today = get_covid_19_cases(CURRENT_CITY)
        except ValueError as e:
            message = get_covid_19_cases(CURRENT_CITY)
            write_to_log(message)
            LOGGED_ERRORS.append(
                message)
            NOTIFICATIONS.append(
                {"title": ("Error - UID:" + str(len(LOGGED_ERRORS))), "content": message})
            # Save the NOTIFICATIONS and the removed alarm too the config
            write_config()
            return index

        # Then create a message to show the covid cases for the day
        # aswell as the total covid cases
        message = "Covid-19 cases today in " + CURRENT_CITY + " " + \
            str(cases_today) + " giving a cumulative total of " + \
            str(total_cases) + " in " + CURRENT_CITY

        # Add this message along with a custom
        # dated title too the NOTIFICATIONS
        NOTIFICATIONS.append({"title": "COVID Statistics Update - " + str(
            datetime.now().strftime("%d/%m/%Y %H:%M")), "content": message})

        # Then loop through the covid-19 news articles
        for covid_article in covid_update:

            # Give the article a title using the date and time as UID
            title = "COVID News Update - " + \
                str(datetime.now().strftime("%d/%m/%Y %H:%M")) +\
                " - Story " + str(covid_update.index(covid_article) + 1)

            NOTIFICATIONS.append(
                {"title": title, "content": covid_article})

    # Run the get_weather to open weather api
    # to get the current weather conditions
    try:
        current_temperature, current_pressure, current_humidiy, \
            weather_description = get_weather(CURRENT_CITY, WEATHER_KEY)
    except ValueError as e:
        message = get_weather(CURRENT_CITY, WEATHER_KEY)
        write_to_log(message)
        LOGGED_ERRORS.append(
            message)

        NOTIFICATIONS.append(
            {"title": ("Error - UID:" + str(len(LOGGED_ERRORS))), "content": message})
        # Save the NOTIFICATIONS and the removed alarm too the config
        write_config()
        return index

    # Add the weather to the NOTIFICATIONS
    NOTIFICATIONS.append(
        {"title": ("Weather Update - " +
                   str(datetime.now().strftime("%d/%m/%Y %H:%M"))),
         "content": ("Temperature (in degrees): " +
                     str(int(current_temperature) - 273) +
                     "\n | Atmospheric pressure (in hPa unit): " +
                     str(current_pressure) +
                     "\n | Humidity (as a percentage): " +
                     str(current_humidiy) +
                     "\n | Current weather: " +
                     str(weather_description))})

    # Add a day too the current briefing time
    date_time = date_time + timedelta(days=1)

    # Calculate the time too the next briefing
    # and then re-add it too the scheduler
    time_to_alarm = (date_time - datetime.now()).total_seconds()
    S.enter(time_to_alarm, 1, run_briefing, (time_select, date_time))

    # Refresh the page
    return index
def test_three():
    weather = get_weather(weather_json)
    assert weather['humidity'] == 95
def test_two():
    weather = get_weather(weather_json)
    assert weather['temperature'] == 13
def test_one():
    weather = get_weather(weather_json)
    assert weather['description'] == 'light rain'
def test_wrong_city():
    assert get_weather(
        "odosfsdo", "1badcdc04f3787dfffa0385872d51f1b") == "Error city name or api key not valid or the openweather api is offline!"
def test_api_key():
    assert get_weather(
        "London", "3243423423424") == "Error city name or api key not valid or the openweather api is offline!"
def test_good_input():
    assert get_weather(
        "London", "1badcdc04f3787dfffa0385872d51f1b") != "Error city name or api key not valid or the openweather api is offline!"
def test_bad_input():
    assert get_weather(
        12345, 12312313) == "Error city name or api key not valid or the openweather api is offline!"
Exemple #14
0
def update_notifications() -> None:
    '''
    This function is used to update notifications with information
    from the news, weather and covid api
    '''

    try:
        for article in get_news(get_news_from_api(news_api_key).json(
        )):  # for each article in the articles from the api
            if article not in notifications and article not in old_notifications:  # if the notification isn't in current notifications and not in old notifications
                notifications.insert(0, {
                    'title': article['title'],
                    'content': article['content']
                })  # insert the notification in the list of notifications
                logging.info('%s:"%s" was added to the list of notifications',
                             datetime.now(), article['title'])
    except:
        logging.error('%s:An error occured with the news API', datetime.now())

    try:
        new_weather = get_weather(
            get_weather_from_api(
                weather_api_key,
                config['city']).json())  # get the weather for the current city
        global CURRENT_WEATHER  # set the variable as a global variable

        if new_weather != CURRENT_WEATHER:  # if the weather has changed
            content = ''
            if new_weather['temperature'] != CURRENT_WEATHER[
                    'temperature']:  # if the temperature changed
                content += ' The temperature has changed from {0}°C to {1}°C.'.format(
                    str(CURRENT_WEATHER['temperature']),
                    str(new_weather['temperature']))

            if new_weather['humidity'] != CURRENT_WEATHER[
                    'humidity']:  # if the humidity changed
                content += ' The level of humidity has changed from {0}% to {1}%.'.format(
                    CURRENT_WEATHER['humidity'], new_weather['humidity'])

            if new_weather['description'] != CURRENT_WEATHER[
                    'description']:  # if the description changed
                content += ' The description of the weather has changed from {0} to {1}.'.format(
                    CURRENT_WEATHER['description'], new_weather['description'])

            notifications.insert(
                0, {
                    'title':
                    'Weather Update - {0}'.format(
                        datetime.now().strftime('%d/%m/%Y %H:%M:%S')),
                    'content':
                    content
                })  # insert the weather update to the notifications
            CURRENT_WEATHER = new_weather  # update the current weather variable
            logging.info('%s:"%s" was added to the list of notifications',
                         datetime.now(), notifications[0]['title'])
    except:
        logging.error('%s:An error occured with the weather API',
                      datetime.now())

    try:
        covid = get_covid()  # get the covid data for england
        cases = covid['newCasesByPublishDate']  # get cases today
        deaths = covid[
            'newDeaths28DaysByPublishDate']  # get deaths today for people who tested positive in the last 28 days
        cases_threshold = config[
            'covid_infected_threshold']  # get the covid infected threshold from the config file
        deaths_threshold = config[
            'covid_death_threshold']  # get the covid death threshold from the config file
        deaths = deaths if deaths else 0  # if deaths is None, set it as 0

        if cases >= cases_threshold or deaths >= deaths_threshold:  # if the cases or deaths is higher than the thresholds
            covid_content = 'Thare are currently {0} new cases today, and {1} new deaths today'.format(
                cases, deaths)
            covid_notif = {'title': 'COVID Update', 'content': covid_content}

            if (covid_notif not in notifications) and (
                    covid_notif
                    not in old_notifications):  # if the notification is new
                notifications.insert(
                    0, covid_notif
                )  # insert the covid update to the notifications
                logging.info('%s:"%s" was added to the list of notifications',
                             datetime.now(), covid_notif['title'])
    except:
        logging.error('%s:An error occured with the covid API', datetime.now())
Exemple #15
0
news_api_key = config['news_api_key']  # extract the news api key

s = sched.scheduler(time.time, time.sleep)  # initialise the schedular
logging.basicConfig(filename='sys.log',
                    level=logging.INFO)  # initialise the logging module

app = Flask(__name__)  # initialise the flask app
app.logger.disabled = True  # disable console logging for flask
logging.getLogger(
    'werkzeug').disabled = True  # disable logging for flask in the log file
logging.getLogger('comtypes.client._code_cache'
                  ).disabled = True  # disable other kind of logging

try:
    CURRENT_WEATHER = get_weather(
        get_weather_from_api(
            weather_api_key,
            config['city']).json())  # get the weather for current city
except:
    logging.error('%s:An error occured with the weather API', datetime.now())


def trigger_alarm(data: dict) -> None:
    '''
    This function is used to trigger an alarm, it is only called on
    when an alarm is meant to go off

    keyword argument:
    data -- the alarm information such as content, title etc.
    '''

    logging.info('Alarm called %s is going off at %s', data['title'],