So I added this line to my crontab at the end of the file, but I cannot seem to get my program to run. I'm not logging anything in my scubot.log so that's not very helpful. Not sure what I'm doing wrong, I've tried several solutions to this but can't seem to find any good information, at least nothing that fits my case.
#reboot sleep 15; /usr/bin/python3 /home/pi/Documents/scubot/scubot.py >> /home/pi/Documents/scubot/scubot.log
from sqlite3 import Date, Error
import ssl
import requests
import configparser
from datetime import date, datetime
import schedule
import time
import emailHelper
from email_templates import emails
# import RPi.GPIO as GPIO
# import time
config = configparser.ConfigParser()
config.read(".config")
configstuff = config['Weather_API']['weatherAPIKey']
lat = "41.6884"
long = "-93.7925"
import pymongo
# Replace the uri string with your MongoDB deployment's connection string.
conn_str = "mongodb+srv://sensitive.nqx9x.mongodb.net/?retryWrites=true&w=majority"
# set a 5-second connection timeout
client = pymongo.MongoClient(conn_str, serverSelectionTimeoutMS=5000)
db = client.scubot
weatherDataCollection = db.weatherdata
# create env to only run this when on the raspberry pi?
import os
import time
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
device_file = '/sys/devices/w1_bus_master1/28-0620111704e4/w1_slave'
print('Scubot Started')
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
print('lines', lines)
return lines
def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
print('temp string', temp_string)
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_f
response = requests.get("https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + long + "&units=imperial&appid=" + configstuff + "").json()
weather = response['main']
city = response['name']
icon = response['weather'][0]['icon']
number1 = 498474239847239
boolean = True
# print(city)
# print(weather)
def storeWeatherData():
try:
weatherData = {
"city": city,
"outsideTemp" : weather['temp'],
"humidity" : weather['humidity'],
"outsidePressure" : weather['pressure'],
"lat": lat,
"long": long,
"shallowProbeTemp": "{:.2f}".format(read_temp()),
"dateOfTempReading": datetime.now()
}
weatherDataCollection.insert_one(weatherData)
print(weatherData, 'Successfully inserted into the database')
except Exception:
print(Exception)
# emailHelper.sendEmail(['test'], 'testing scuba app', emails.temperatureEmail(weather['temp'], lat, long))
# # This uses a scheduler to run a certain function every day. We can set this to minutes or hours or days.
schedule.every(1).minutes.do(storeWeatherData)
while True:
schedule.run_pending()
time.sleep(1)
I have this script that runs continuously on a raspbery Zero to capture the temperatures and send them to grafana the problem is that when the grafana server is stopped for backup or something, the script falls in error and does not automatically resume so I’m looking for a way to create a connection test loop prealable to sending data and if the grafana server is off-service the continuous script worked until the grafana server was up and running and therefore resumed sending the temperature data to the grafana server.
Because current I end up with the script in error with in the message
requests.exceptions.ConnectionError: HTTPConnectionPool
To use script
python templogger.py -db=influx_db_temperature -sn=temperature -rn=RUN
My script :
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import glob
import argparse
import time
import datetime
import sys
from influxdb import InfluxDBClient
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
# add more sensor variables here based on your setup
# For multiple sensor
# temp=['sensor code','tttttttttt','ddddddddddd','ssssssssss']
temp=['0120215dbea2','0120327e05bf']
base_dir = '/sys/bus/w1/devices/'
# Ext = 28-0120215dbea2
# Int = 28-0120327e05bf
device_folders = glob.glob(base_dir + '28*')
snum=2 #Number of connected temperature sensors
# Set required InfluxDB parameters.
# (this could be added to the program args instead of beeing hard coded...)
host = "NasGrafana.lan.prive" #Could also use local ip address like "192.168.1.136"
port = 8086
user = "temperature"
password = "12345678"
# Sample period (s).
# How frequently we will write sensor data from the temperature sensors to the database.
sampling_period = 120
def read_temp_raw(device_file):
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp(device_file): # checks the temp recieved for errors
lines = read_temp_raw(device_file)
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw(device_file)
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
# set proper decimal place for C
temp = float(temp_string) / 1000.0
# Round temp to 2 decimal points
temp = round(temp, 1)
# value of temp might be unknown here if equals_pos == -1
return temp
def get_args():
'''This function parses and returns arguments passed in'''
# Assign description to the help doc
parser = argparse.ArgumentParser(description='Program writes measurements data from the connected DS18B20 to specified influx db.')
# Add arguments
parser.add_argument(
'-db','--database', type=str, help='Database name', required=True)
parser.add_argument(
'-sn','--session', type=str, help='Session', required=True)
now = datetime.datetime.now()
parser.add_argument(
'-rn','--run', type=str, help='Run number', required=False,default=now.strftime("%Y%m%d%H%M"))
# Array of all arguments passed to script
args=parser.parse_args()
# Assign args to variables
dbname=args.database
runNo=args.run
session=args.session
return dbname, session,runNo
def get_data_points():
# Get the three measurement values from the DS18B20 sensors
for sensors in range (snum): # change number of sensors based on your setup
device_file=device_folders[sensors]+ '/w1_slave'
temp[sensors] = read_temp(device_file)
print (device_file,sensors,temp[sensors])
# Get a local timestamp
timestamp=datetime.datetime.utcnow().isoformat()
NumDevice=os.path.basename(os.path.dirname(device_file))
# Create Influxdb datapoints (using lineprotocol as of Influxdb >1.1)
datapoints = [
{
"measurement": session,
# "tags": {"runNum": NumDevice,},
"tags": {"runNum": runNo,},
"time": timestamp,
#"fields": {"temperature 1":temp[0],"temperature 2":temp[1],"temperature 3":temp[2],"temperature 4":temp[3]}
"fields": {"temperature 1":temp[0],"temperature 2":temp[1]}
}
]
return datapoints
# Match return values from get_arguments()
# and assign to their respective variables
dbname, session, runNo =get_args()
print ("Session: ", session)
print ("Run No: ", runNo)
print ("DB name: ", dbname)
# Initialize the Influxdb client
client = InfluxDBClient(host, port, user, password, dbname)
try:
while True:
# Write datapoints to InfluxDB
datapoints=get_data_points()
bResult=client.write_points(datapoints)
print("Write points {0} Bresult:{1}".format(datapoints,bResult))
# Wait for next sample
time.sleep(sampling_period)
# Run until keyboard ctrl-c
except KeyboardInterrupt:
print ("Program stopped by keyboard interrupt [CTRL_C] by user. ")
Thank you #AbhinavMathur for forcing me to stay on adding a try-except because in the end it’s just that I wasn’t positioning correctly in the script
This is the modif allowing the script to not crash with a connection error.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import glob
import argparse
import time
import datetime
import sys
from influxdb import InfluxDBClient
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
# add more sensor variables here based on your setup
# For multiple sensor
# temp=['sensor code','tttttttttt','ddddddddddd','ssssssssss']
temp=['0120215dbea2','0120327e05bf']
base_dir = '/sys/bus/w1/devices/'
# Ext = 28-0120215dbea2
# Int = 28-0120327e05bf
device_folders = glob.glob(base_dir + '28*')
snum=2 #Number of connected temperature sensors
# Set required InfluxDB parameters.
# (this could be added to the program args instead of beeing hard coded...)
host = "NasGrafana.lan.prive" #Could also use local ip address like "192.168.1.136"
port = 8086
user = "temperature"
password = "12345678"
# Sample period (s).
# How frequently we will write sensor data from the temperature sensors to the database.
sampling_period = 120
def read_temp_raw(device_file):
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp(device_file): # checks the temp recieved for errors
lines = read_temp_raw(device_file)
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw(device_file)
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
# set proper decimal place for C
temp = float(temp_string) / 1000.0
# Round temp to 2 decimal points
temp = round(temp, 1)
# value of temp might be unknown here if equals_pos == -1
return temp
def get_args():
'''This function parses and returns arguments passed in'''
# Assign description to the help doc
parser = argparse.ArgumentParser(description='Program writes measurements data from the connected DS18B20 to specified influx db.')
# Add arguments
parser.add_argument(
'-db','--database', type=str, help='Database name', required=True)
parser.add_argument(
'-sn','--session', type=str, help='Session', required=True)
now = datetime.datetime.now()
parser.add_argument(
'-rn','--run', type=str, help='Run number', required=False,default=now.strftime("%Y%m%d%H%M"))
# Array of all arguments passed to script
args=parser.parse_args()
# Assign args to variables
dbname=args.database
runNo=args.run
session=args.session
return dbname, session,runNo
def get_data_points():
# Get the three measurement values from the DS18B20 sensors
for sensors in range (snum): # change number of sensors based on your setup
device_file=device_folders[sensors]+ '/w1_slave'
temp[sensors] = read_temp(device_file)
print (device_file,sensors,temp[sensors])
# Get a local timestamp
timestamp=datetime.datetime.utcnow().isoformat()
NumDevice=os.path.basename(os.path.dirname(device_file))
# Create Influxdb datapoints (using lineprotocol as of Influxdb >1.1)
datapoints = [
{
"measurement": session,
# "tags": {"runNum": NumDevice,},
"tags": {"runNum": runNo,},
"time": timestamp,
#"fields": {"temperature 1":temp[0],"temperature 2":temp[1],"temperature 3":temp[2],"temperature 4":temp[3]}
"fields": {"temperature 1":temp[0],"temperature 2":temp[1]}
}
]
return datapoints
# Match return values from get_arguments()
# and assign to their respective variables
dbname, session, runNo =get_args()
print ("Session: ", session)
print ("Run No: ", runNo)
print ("DB name: ", dbname)
# Initialize the Influxdb client
client = InfluxDBClient(host, port, user, password, dbname)
try:
while True:
# Write datapoints to InfluxDB
datapoints=get_data_points()
try:
bResult=client.write_points(datapoints)
print("Write points {0} Bresult:{1}".format(datapoints,bResult))
except:
print("Error lan connection")
#time.sleep(30)
#continue
# Wait for next sample
time.sleep(sampling_period)
# Run until keyboard ctrl-c
except KeyboardInterrupt:
print ("Program stopped by keyboard interrupt [CTRL_C] by user. ")
In this script I am taking the temperature from a DHT11 sensor and parsing the data that another script can read. Everything works except for writing the file to another pc using the path I placed in the f = open part of the script below. Everything works great except that the file doesn't get written or saved.
Any Help?
#!/usr/bin/env python
# encoding: utf-8
import sys
import time
import dht11
import RPi.GPIO as GPIO
#define GPIO 14 as DHT11 data pin
Temp_sensor=14
def main():
# Main program block
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers
instance = dht11.DHT11(pin = Temp_sensor)
while True:
#get DHT11 sensor value
result = instance.read()
temp = '{:.0f}'.format(result.temperature * 1.8 + 32)+"°"
# The path to send the txt file to and save is /10.1.1.28/c$/Temperature_RETR/kvoa_temp.txt
if result.is_valid():
print temp
f = open('\\10.1.1.28\c$\Temperature_RETR\new_temp.txt','w')
#f = open('/home/pi/Desktop/new_temp.txt','w')
y = temp
z = str(y)
f.write(z)
f.close()
time.sleep(60) # 60 second delay
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
I'm using this python script:
LINK
It's working great so far.
But now I would like to optimize it, because sometimes it's happening that the script will be executed 2-3 times within 10-20 minutes, because it will always run if there are 3 streams or more (e.g. a 4. stream will be started --> notification will be send again or also if a user decide to cancel this stream and watch another movie --> The script will run again!)
I have tried to use time.sleep but that is not working. I would like to have it like this:
If the program will be executed,it shouldn't be run again within the next 60 minutes.
What do I need to use / code here?
Thanks for help!
Thank you for the Tip, my code does look like this now (can you maybe check?):
** code section ** = my code which I have merged inside the existing script.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Description: Send a PlexPy notification when the total
# number of streams exceeds a threshold.
# Author: /u/SwiftPanda16
# Requires: requests
# PlexPy script trigger: Playback start
# PlexPy script arguments: {streams}
import requests
import sys
**import os
from datetime import datetime, timedelta**
### EDIT SETTINGS ###
PLEXPY_URL = 'xx.xxx.xx:8181'
PLEXPY_APIKEY = 'xxxxxxxxxxxxxxxxxx'
AGENT_ID = 14 # The PlexPy notifier agent id found here: https://github.com/JonnyWong16/plexpy/blob/master/API.md#notify
NOTIFY_SUBJECT = 'test' # The notification subject
NOTIFY_BODY = 'Test'
STREAM_THRESHOLD = 3
**### time management ###
one_hour_ago = datetime.now() - timedelta(minutes=60)
filetime = datetime.fromtimestamp(os.path.getctime("timestamp.txt"))
if filetime < one_hour_ago:**
### CODE BELOW ###
def main():
try:
streams = int(sys.argv[1])
except:
print("Invalid PlexPy script argument passed.")
return
if streams >= STREAM_THRESHOLD:
print("Number of streams exceeds {threshold}.".format(threshold=STREAM_THRESHOLD))
print("Sending PlexPy notification to agent ID: {agent_id}.".format(agent_id=AGENT_ID))
params = {'apikey': PLEXPY_APIKEY,
'cmd': 'notify',
'agent_id': AGENT_ID,
'subject': NOTIFY_SUBJECT,
'body': NOTIFY_BODY}
r = requests.post(PLEXPY_URL.rstrip('/') + '/api/v2', params=params)
**os.getcwd()
open ('timestamp.txt', 'w')**
else:
print("Number of streams below {threshold}.".format(threshold=STREAM_THRESHOLD))
print("No notification sent.")
return
if __name__ == "__main__":
main()
**else:
pass**
Have the script write a timestamp to an external file and check that file at startup.
Here is an example:
import time
def script_has_run_recently(seconds):
filename = 'last-run-time.txt'
current_time = int(time.time())
try:
with open(filename, 'rt') as f:
last_run = int(f.read().strip())
except (IOError, ValueError) as e:
last_run = 0
if last_run + seconds > current_time:
return True
else:
with open(filename, 'wt') as f:
f.write(str(current_time))
return False
def main():
print('running the main function.')
if __name__ == "__main__":
seconds = 3600 # one hour in seconds
if script_has_run_recently(seconds):
print('you need to wait before you can run this again')
else:
main()
This a somewhat general question so forgive me if I'm breaking any guidelines.
I'm writing a JQuery / websocket / Flask application that uses a Raspberry Pi to monitor some sensors as well as manage some active hardware. Multiple classes and objects spawned by my Flask-implemented server need to be able to access my hardware.
Based off my programming background (relatively new to Python) I would gravitate to a static class with class methods that operate without instantiation.
I've found documentation on how to do that in Python but I'm not sure it's the best approach. Is it more Pythonic to instantiate an object and pass it around or ... ?
Here is the non-static object oriented code I'm using now (I'm thinking a static version of the following will suite my needs but I want to do what is most appropriate for the language):
import os
import glob
import time
import RPi.GPIO as GPIO
#class to manage hardware -- sensors, pumps, etc
class Hardware:
#system params for sensor
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
#global vars for sensor
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
#global var for program
temp_unit = 'F' #temperature unit, choose C for Celcius or F for F for Farenheit
temp_target = 69 #target temperature to cool to in chosen unit
temp_log_loc = '/var/www/hw-log.csv' #location of temp log, by default Raspberry Pi Apache server
gpio_pin = 17
#function to enable GPIO
def gpio_active(self,active):
if active is True:
GPIO.setmode(GPIO.BCM)
GPIO.setup(self.gpio_pin, GPIO.OUT)
else:
GPIO.cleanup()
#def __init__(self): Not used
#reads raw temp from sensor
def read_temp_raw(self):
f = open(self.device_file, 'r')
lines = f.readlines()
f.close()
return lines
#cleans up raw sensor data, returns temp in unit of choice
def read_temp(self):
lines = self.read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = self.read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
if self.temp_unit == 'F':
return temp_f
else:
return temp_c
#**********sensors**********
#mashtun sensor
##staticmethod
def mashtun_temp(self):
return self.read_temp()
#hot liquor tank sensor
def htl_temp(self):
return 200
#fermentor sensor
def fermentor_temp(self):
return 65
#**********pumps**********
def herms_pump_active(self,active):
self.gpio_active(True)
if active is True:
print('***Hardware report: Setting HERMS pump on***')
GPIO.output(self.gpio_pin,GPIO.LOW)
else:
print('Setting HERMS pump off')
GPIO.output(self.gpio_pin,GPIO.HIGH)
self.gpio_active(False)