提问人:xampL 提问时间:8/10/2023 最后编辑:xampL 更新时间:8/10/2023 访问量:53
Json 多线程问题?
Json multithreading issue?
问:
我非常不熟悉使用JSON文件来存储信息,并且收到一个错误,说明我在调试时遇到问题。在某些情况下,这是一个树莓派温室项目,我正在尝试使用 json 文件来存储数据,以便在我打开和关闭系统时存储数据。这是我不断收到的错误:
>>> Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
self.run()
File "/usr/lib/python3.9/threading.py", line 892, in run
self._target(*self._args, **self._kwargs)
File "/home/ben6brewer/Desktop/Greenhouse/GreenHouse.py", line 214, in lcd_updater
self.lcd_display.screen2(self.get_minutes_elapsed())
File "/home/ben6brewer/Desktop/Greenhouse/GreenHouse.py", line 227, in get_minutes_elapsed
data = json.load(json_file)
File "/usr/lib/python3.9/json/__init__.py", line 293, in load
return loads(fp.read(),
File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 35 column 5 (char 532)
以下是我的主要温室课程:
import time
import threading
from datetime import datetime
import RPi.GPIO as GPIO
import Adafruit_DHT
from LCD import LCDDisplay
from CreateGraph import GraphGenerator
from SendEmail import EmailSender
from time import sleep
from LCD import LCDScreens
import sys
import select
import json
import os
class GreenhouseController:
def __init__(self):
self.relay_pins = [24, 25]
self.fan_pin = self.relay_pins[0]
self.mist_pin = self.relay_pins[1]
self.lowest_temp = 65 # degrees F
self.highest_temp = 80 # degrees F
self.lowest_humidity = 80 # %
self.highest_humidity = 90 # %
self.graph_generator = GraphGenerator() # Instantiate the GraphGenerator class
self.email_sender = EmailSender()
self.lcd_display = LCDDisplay(controller=self)
self.minute_temperature_data = []
self.minute_humidity_data = []
self.hour_temperature_data = []
self.hour_humidity_data = []
self.current_second = int(time.time() % 60)
self.last_second = None
self.current_minute = int(time.time() // 60) % 60
self.last_minute = None
self.program_start_minute = int(time.time() // 60) % 60
self.current_hour = int(time.time() // 3600) % 24
self.last_hour = None
self.program_start_hour = int(time.time() // 3600) % 24
self.relative_count = 0
self.system_activated = False
self.humidity = 0
self.temperature = 0
# Get the absolute path to the current script's directory
# path to json = '/home/ben6brewer/Desktop/Greenhouse/data.json'
# Set up GPIO pins
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(self.fan_pin, GPIO.OUT)
GPIO.setup(self.mist_pin, GPIO.OUT)
def main(self):
try:
self.run_lcd()
while True:
self.check_user_input()
if self.first_iteration_check():
self.send_boot_message()
self.update_time()
self.update_variables()
# TRUE every 1 minute
if self.minute_check():
self.minute_operations()
# True every 10 minutes:
if self.ten_minute_check():
self.ten_minute_operations()
# TRUE every 1 HOUR
if self.hour_check():
self.hour_operations()
# TRUE every 1 day
if self.day_check():
self.day_operations()
self.system_activated = False
if self.humidity_check():
self.activate_humidity()
if self.temperature_check():
self.activate_fans()
if self.system_activated == False:
sleep(2)
except KeyboardInterrupt:
pass
GPIO.cleanup()
@staticmethod
def get_current_temperature():
return round((Adafruit_DHT.read_retry(22, 4)[1]) * 9/5 + 32, 2)
@staticmethod
def get_current_humidity():
return round(Adafruit_DHT.read_retry(22, 4)[0], 2)
# Turns pump on for parameterized seconds
def pump_on(self, seconds):
GPIO.output(self.mist_pin, 0)
sleep(seconds)
GPIO.output(self.mist_pin, 1)
self.add_to_total_pump_time(seconds)
if self.get_total_pump_time() > 60:
self.email_sender.send_pump_warning(self.get_total_pump_time())
self.reset_total_pump_time()
# Turns pump on for parameterized seconds
def fans_on(self, seconds):
GPIO.output(self.fan_pin, 0)
sleep(seconds)
GPIO.output(self.fan_pin, 1)
def get_days_elapsed(self):
return round(self.get_minutes_elapsed() / 1440, 2)
def update_time(self):
self.current_second = int(time.time() % 60)
self.current_minute = int(time.time() // 60) % 60
self.current_hour = int(time.time() // 3600) % 24
def update_variables(self):
self.humidity = self.get_current_humidity()
self.temperature = self.get_current_temperature()
def minute_check(self):
return (self.last_minute is None or self.last_minute != self.current_minute)
def minute_operations(self):
self.last_minute = self.current_minute
self.append_temperature_to_minute_array(self.temperature)
self.append_humidity_to_minute_array(self.humidity)
self.update_minutes_in_json(1)
def ten_minute_check(self):
return ((self.program_start_minute % 10) == (self.current_minute % 10))
def ten_minute_operations(self):
self.fans_on(45)
sleep(45)
def first_iteration_check(self):
return (self.relative_count == 0)
def send_boot_message(self):
self.email_sender.send_boot_email(self.get_days_elapsed())
def hour_check(self):
return ((self.program_start_minute) == (self.current_minute))
def hour_operations(self):
average_temperature = round((sum(self.get_temperature_minute_array())) / len(self.get_temperature_minute_array()), 2)
self.append_temperature_to_hour_array(average_temperature)
average_humidity = round((sum(self.get_humidity_minute_array())) / len(self.get_humidity_minute_array()), 2)
self.append_humidity_to_hour_array(average_humidity)
self.reset_minute_arrays()
self.relative_count += 1
def day_check(self):
minutes_elapsed = self.get_minutes_elapsed()
return (minutes_elapsed >= 1440 and minutes_elapsed % 1440 == 0 and self.relative_count > 1)
def day_operations(self):
self.graph_generator.create_graph(self.get_days_elapsed(), [self.get_temperature_hour_array(), self.get_humidity_hour_array()])
self.email_sender.send_email(self.get_days_elapsed())
self.reset_hour_arrays()
def humidity_check(self):
return (self.humidity <= self.lowest_humidity)
def activate_humidity(self):
if self.get_current_humidity() < (self.lowest_humidity - 20):
self.pump_on(30)
elif self.get_current_humidity() < (self.lowest_humidity - 10):
self.pump_on(20)
else:
self.pump_on(5)
sleep(10)
self.system_activated = True
def temperature_check(self):
return (self.temperature >= self.highest_temp or self.humidity >= self.highest_humidity)
def activate_fans(self):
if self.get_current_humidity() > self.highest_humidity:
self.fans_on(20)
elif self.get_current_temperature() > (self.highest_temp):
self.fans_on(20)
else:
self.fans_on(10)
self.system_activated = True
def lcd_updater(self):
current_screen = LCDScreens.SCREEN1
while True:
if current_screen == LCDScreens.SCREEN1:
self.lcd_display.screen1(self.get_current_temperature(), self.get_current_humidity())
elif current_screen == LCDScreens.SCREEN2:
self.lcd_display.screen2(self.get_minutes_elapsed())
# Switch to the next screen
current_screen = LCDScreens.SCREEN1 if current_screen == LCDScreens.SCREEN2 else current_screen + 1
sleep(5) # Adjust the delay time as needed (in seconds)
def run_lcd(self):
self.lcd_thread = threading.Thread(target=self.lcd_updater)
self.lcd_thread.daemon = True
self.lcd_thread.start()
def get_minutes_elapsed(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r') as json_file:
data = json.load(json_file)
minutes_elapsed = data.get('minutes', 0)
return minutes_elapsed
def update_minutes_in_json(self, minutes_to_add):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
current_minutes = data.get('minutes', 0)
new_minutes = current_minutes + minutes_to_add
data['minutes'] = new_minutes
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def reset_json_data(self):
data = {
"minutes": 0,
"TotalPumpTime": 0,
"TemperatureMinuteArray": [],
"HumidityMinuteArray": [],
"TemperatureHourArray": [],
"HumidityHourArray": []
}
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'w') as json_file:
json.dump(data, json_file, indent=4)
def append_temperature_to_minute_array(self, temperature):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
temperature_array = data.get('TemperatureMinuteArray', [])
temperature_array.append(temperature)
data['TemperatureMinuteArray'] = temperature_array
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def append_humidity_to_minute_array(self, humidity):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json','r+') as json_file:
data = json.load(json_file)
humidity_array = data.get('HumidityMinuteArray', [])
humidity_array.append(humidity)
data['HumidityMinuteArray'] = humidity_array
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def append_temperature_to_hour_array(self, temperature):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
temperature_array = data.get('TemperatureHourArray', [])
temperature_array.append(temperature)
data['TemperatureHourArray'] = temperature_array
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def append_humidity_to_hour_array(self, humidity):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
humidity_array = data.get('HumidityHourArray', [])
humidity_array.append(humidity)
data['HumidityHourArray'] = humidity_array
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def reset_minute_arrays(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
data['TemperatureMinuteArray'] = []
data['HumidityMinuteArray'] = []
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def reset_hour_arrays(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
data['TemperatureHourArray'] = []
data['HumidityHourArray'] = []
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def get_temperature_minute_array(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r') as json_file:
data = json.load(json_file)
temperature_array = data.get('TemperatureMinuteArray', [])
return temperature_array
def get_humidity_minute_array(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r') as json_file:
data = json.load(json_file)
humidity_array = data.get('HumidityMinuteArray', [])
return humidity_array
def get_temperature_hour_array(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r') as json_file:
data = json.load(json_file)
temperature_array = data.get('TemperatureHourArray', [])
return temperature_array
def get_humidity_hour_array(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r') as json_file:
data = json.load(json_file)
humidity_array = data.get('HumidityHourArray', [])
return humidity_array
def add_to_total_pump_time(self, pump_time):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
total_pump_time = data.get('TotalPumpTime', 0)
total_pump_time += pump_time
data['TotalPumpTime'] = total_pump_time
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def get_total_pump_time(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r') as json_file:
data = json.load(json_file)
total_pump_time = data.get('TotalPumpTime', 0)
return total_pump_time
def reset_total_pump_time(self):
with open('/home/ben6brewer/Desktop/Greenhouse/data.json', 'r+') as json_file:
data = json.load(json_file)
data['TotalPumpTime'] = 0
json_file.seek(0)
json.dump(data, json_file, indent=4)
json_file.truncate()
def check_user_input(self):
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
if rlist:
user_input = sys.stdin.readline().strip()
if user_input:
words = user_input.split()
val = None
if words[-1].isdigit():
val = int(words.pop())
command = ' '.join(words)
if command == 'read vars':
print('temperature: ' + str(self.get_current_temperature()) + ' F')
print('humidity: ' + str(self.get_current_humidity()) + ' %')
elif command == 'get time':
weeks = self.get_minutes_elapsed() // 10080 # 10080 minutes = 7 days (1 week)
remaining_minutes = self.get_minutes_elapsed() % 10080
days = remaining_minutes // 1440 # 1440 minutes = 1 day
remaining_minutes %= 1440
hours = remaining_minutes // 60 # 60 minutes = 1 hour
minutes = remaining_minutes % 60
print(f'Week: {weeks}, Day: {days}, Hour: {hours}, Minute: {minutes}')
elif command == 'stall':
print('sleeping for ' + str(val) + ' seconds')
sleep(val)
self.update_minutes_in_json(val//60)
print('done sleeping')
elif command == 'pump on':
GPIO.output(self.mist_pin, 0)
print('pump on for ' + str(val) + ' seconds')
sleep(val)
GPIO.output(self.mist_pin, 1)
print('pump off')
elif command == 'fans on':
GPIO.output(self.fan_pin, 0)
print('fans on for ' + str(val) + ' seconds')
sleep(val)
GPIO.output(self.fan_pin, 1)
print('fans off')
elif command == 'pump off':
GPIO.output(self.mist_pin, 1)
print('pump off')
elif command == 'fans off':
GPIO.output(self.fan_pin, 1)
print('fans off')
elif command == 'set lowest humidity':
print('setting lowest humidity to ' + str(val) + '%')
self.lowest_humidity = val
print('updated self.lowest_humidity')
elif command == 'set highest humidity':
print('setting highest humidity to ' + str(val) + '%')
self.highest_humidity = val
print('updated self.highest_humidity')
elif command == 'set lowest temperature':
print('setting lowest temp to ' + str(val) + 'F')
self.lowest_temp = val
print('updated self.lowest_temp')
elif command == 'set highest temperature':
print('setting highest temp to ' + str(val) + 'F')
self.highest_temp = val
print('updated self.highest_temp')
elif command == 'AGT preset':
self.lowest_temp = 63
self.highest_temp = 80
self.lowest_humidity = 80
self.highest_humidity = 90
print(f'temp range: {self.lowest_temp}-{self.highest_temp}, humidity range {self.lowest_humidity}-{self.highest_humidity}')
print('Reset Minutes.txt to 0')
self.reset_json_data()
elif command == 'SG preset':
self.lowest_temp = 60
self.highest_temp = 80
self.lowest_humidity = 40
self.highest_humidity = 55
print(f'temp range: {self.lowest_temp}-{self.highest_temp}, humidity range {self.lowest_humidity}-{self.highest_humidity}')
print('Reset Minutes.txt to 0')
self.reset_json_data()
elif command == 'reset':
print('clearing data')
self.reset_json_data()
print('data cleared')
else:
print()
print('list valid requests:')
print()
print('GETTERS / SETTERS:')
print('get vars - gets temperature and humidity')
print('get time - gets current time statistics')
print('stall (seconds) - stalls for x amount of seconds')
print('set minutes (minutes) - set the minutes elapsed')
print('set lowest humidity (%) - updates self.lowest_humidity')
print('set highest humidity (%) - updates self.highest_humidity')
print('set lowest temperature (F) - updates self.lowest_temp')
print('set highest temperature (F) - updates self.highest_temp')
print()
print('HARDWARE CONTROLS:')
print('pump on (seconds) - turns humidifier on for x seconds')
print('fans on (seconds) - turns fans on for x seconds')
print('pump off - turns humidifier off')
print('fans off - turns fans off')
print()
print('PRESET GROWING CONDITIONS:')
print('AGT preset - ideal growing conditions for AGT')
print('SG preset - ideal growing conditions for Super Greens')
print()
print('SYSTEM RESET')
print('reset - clears the json storage file')
controller = GreenhouseController()
controller.main()
下面是 JSON:
{
"minutes": 34079,
"TotalPumpTime": 50,
"TemperatureMinuteArray": [
66.92,
66.92,
67.1,
67.28,
67.46,
67.46,
67.64,
67.82,
68.0,
67.64,
67.82,
67.82
],
"HumidityMinuteArray": [
79.1,
81.7,
84.8,
87.8,
89.8,
87.1,
86.6,
88.2,
89.2,
81.7,
82.3,
85.7
],
"TemperatureHourArray": [
69.08,
68.44,
],
"HumidityHourArray": [
93.7,
84.73,
]
}
我希望能够继续将数据存储在JSON中,我只是无法弄清楚这个错误是什么。
答: 暂无答案
评论
[ 69.08, ]