matiasandina / FEDWatcher

Software and Hardware to connect FED3 devices over serial on Raspberry Pi 4
MIT License
4 stars 1 forks source link

Detecting jams & Notifying People #5

Closed matiasandina closed 1 year ago

matiasandina commented 3 years ago
matiasandina commented 2 years ago

I want to reopen this. We didn't have the best of experience with setting up emails and stuff...there might be a workaround by using something like twillio (or any other app) + python authomation + whatsapp

See here twillio

See here telegram

matiasandina commented 1 year ago

We can send messages with something like this (given we have secrets.py) and have done the telegram configuration. We would need to integrate the proper messaging with parsing data for each FED and/or jamming events and send proper messaging.

Brainstorm of what would be nice to have:

import requests
from secrets import secrets
import seaborn as sns
# Send a telegram message to a given user id
def send_message (chatId, message):
    response = requests.post(sendURL + "?chat_id=" + str(chatId) + "&text=" + message)
    # Close to avoid filling up the RAM.
    response.close()

if __name__ == '__main__':
    botToken = secrets['botToken']
    chatId = secrets['telegramDmUid']

    # Telegram send message URL
    sendURL = 'https://api.telegram.org/bot' + botToken + '/sendMessage'

    iris = sns.load_dataset('iris')
    message =  str(iris.head())

    send_message(chatId, message)
cameron4young commented 1 year ago

Here's what I've coded for the runHelper and event_summary functions:

Lines 235-247 (runHelper):

            # TODO: replicate this idea but with the notification interval
            if (now - self.last_notif * 3600) > self.notif_interval:
                self._save_all_df()
                # create read_csv_
                self.last_save = now
                current_directory = os.getcwd() # gets path to current folder (src)
                data_folder_path = os.path.join(current_directory, 'data') # gets the path to the data folder
                csv_files = [file for file in os.listdir(data_folder_path) if file.endswith('.csv')]
                for path in csv_files:
                    summary = self.event_summary(path)
                    if self.tg_enabled:
                        self.send_tg_message(message=summary)
                self.last_notif = now # updates last_notif to the current time

Event summary:

def event_summary(self, path):
    ## want to return message in format "FED{Device #} delivered {num_rows} pellets since {Time}"
    # INPUTS: data, last time interval
    # OUTPUTS: a summarized message in string form

    # iterate through dataframe
    df = pd.read_csv(path)
    device_number = path.split("_")[0]
    # filter through events using PiTime
    filtered_df = df.loc[df['Pi_Time'] > self.last_notif & (df['Pi_Time'] < self.now) & (df['Event']=="Pellet")]
    # pellets = number of rows in df after filtering
    num_pellets = len(filtered_df.index) # will this work with empty df?
    return f"FED{device_number} delivered {num_pellets} since {self.last_notif}"

The function accesses the 'data' folder by using the os.path.join function. A list of paths to all of the csv files are then created. This list is iterated upon, with each file being read and turned into a pandas dataframe within the event_summary function. After the conversion to a pandas dataframe, the dataframe is filtered to only show the data we are interested in, and a summary message is then created and sent. After all of this happens, we then set the last_notif variable to now, and the process repeats every notif_interval.

matiasandina commented 1 year ago

Thanks for the input @cameron4young. As it is, this will not run. Here are a few of parts that I needed to modify. Currently testing.

These lines are searching for data where the data is not being saved

current_directory = os.getcwd() # gets path to current folder (src)
data_folder_path = os.path.join(current_directory, 'data') # gets the path to the data folder

Data gets saved in

self.exp_dir 

and split by day into

self.today_dir
matiasandina commented 1 year ago

Also, this line turned out to be wrong

filtered_df = df.loc[df['Pi_Time'] > self.last_notif & (df['Pi_Time'] < self.now_dt) & (df['Event']=="Pellet")]
TypeError: Cannot perform 'rand_' with a dtyped [bool] array and scalar of type [bool]

The issue were missing parenthesis on the first condition


More importantly this code didn't reset the last_notif and therefore it was blasting notifications one after the other on each iteration. It was missing

self.last_notif = self.now_dt
matiasandina commented 1 year ago

Looks like mvp is working. Closing until further enhancement is needed. image