Skip to content

Commit

Permalink
v0.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
GlassOnTin committed Nov 15, 2024
1 parent 6e09543 commit d1ca84a
Show file tree
Hide file tree
Showing 9 changed files with 463 additions and 14 deletions.
16 changes: 15 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ if ! ./tools/verify-versions.sh; then
exit 1
fi

echo "Setting up web interface structure..."
mkdir -p gecko_controller/web/templates
[ ! -f gecko_controller/web/__init__.py ] && touch gecko_controller/web/__init__.py

echo "Building Debian package..."
if ! dpkg-buildpackage -us -uc; then
echo "Error: Package build failed"
Expand All @@ -21,4 +25,14 @@ fi

echo "Build completed successfully!"
echo "Package files created in parent directory:"
ls -l ../*.deb ../*.buildinfo ../*.changes
ls -l ../*.deb ../*.buildinfo ../*.changes

echo
echo "Next steps:"
echo "1. Install the package: sudo dpkg -i ../gecko-controller_*.deb"
echo "2. Install dependencies: sudo apt-get install -f"
echo "3. Start the web interface: sudo systemctl start gecko-web"
echo "4. Enable web interface autostart: sudo systemctl enable gecko-web"
echo "5. Check status: sudo systemctl status gecko-web"
echo
echo "The web interface will be available at http://localhost:8080"
19 changes: 12 additions & 7 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ Depends: ${python3:Depends},
${misc:Depends},
python3-pip,
python3-venv,
i2c-tools,
python3 (>= 3.9)
Description: Raspberry Pi Gecko Enclosure Controller
Automated temperature and light controller for gecko enclosure
with OLED status display. Monitors temperature and humidity,
controls lighting cycles, manages heating, and displays status
on an OLED screen.
python3 (>= 3.9),
python3-rpi.gpio,
python3-pillow,
python3-smbus,
python3-flask,
i2c-tools
Description: Raspberry Pi Gecko Vivarium Controller
Automated environmental controller for gecko vivarium with OLED status
display. Monitors temperature and humidity, controls day/night lighting
cycles, manages heating, and provides both OLED display and web interface
for status monitoring and configuration. Includes UV monitoring for
optimal basking conditions.
13 changes: 13 additions & 0 deletions debian/gecko-web.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=Gecko Controller Web Interface
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/gecko-web
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target
2 changes: 2 additions & 0 deletions debian/gecko-web.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exec python3 -m gecko_controller.web.app
4 changes: 3 additions & 1 deletion debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ override_dh_auto_install:
mkdir -p debian/gecko-controller/etc/gecko-controller
mkdir -p debian/gecko-controller/lib/systemd/system
install -m 755 debian/gecko-controller.sh debian/gecko-controller/usr/bin/gecko-controller
install -m 755 debian/gecko-web.sh debian/gecko-controller/usr/bin/gecko-web
install -m 644 debian/gecko-controller.service debian/gecko-controller/lib/systemd/system/
install -m 644 debian/gecko-web.service debian/gecko-controller/lib/systemd/system/
install -m 644 debian/config.py debian/gecko-controller/etc/gecko-controller/

override_dh_auto_test:
:
:
Empty file.
128 changes: 128 additions & 0 deletions gecko_controller/web/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env python3
# gecko_controller/web/app.py
from flask import Flask, render_template, jsonify, request
import os
import re
import csv
from datetime import datetime
import pkg_resources

app = Flask(__name__)
app.template_folder = pkg_resources.resource_filename('gecko_controller.web', 'templates')

CONFIG_FILE = '/etc/gecko-controller/config.py'
LOG_FILE = '/var/log/gecko-controller/readings.log'

def read_config():
"""Read and parse the config file"""
config = {}
with open(CONFIG_FILE, 'r') as f:
content = f.read()
# Extract key-value pairs using regex
pairs = re.findall(r'(\w+)\s*=\s*([^#\n]+)', content)
for key, value in pairs:
# Clean up the value
value = value.strip().strip('"\'')
try:
# Try to evaluate as Python literal
import ast
config[key] = ast.literal_eval(value)
except:
# If not a literal, store as string
config[key] = value
return config

def write_config(config):
"""Write config back to file"""
# Read existing file to preserve comments and structure
with open(CONFIG_FILE, 'r') as f:
lines = f.readlines()

# Update values while preserving structure
new_lines = []
for line in lines:
if '=' in line and not line.strip().startswith('#'):
key = line.split('=')[0].strip()
if key in config:
value = config[key]
if isinstance(value, str) and not key.endswith('_THRESHOLDS'):
value = f'"{value}"'
new_lines.append(f'{key} = {value}\n')
else:
new_lines.append(line)

# Write back to file
with open(CONFIG_FILE, 'w') as f:
f.writelines(new_lines)

def read_logs(hours=24):
"""Read the last N hours of log data"""
data = {
'timestamps': [],
'temperature': [],
'humidity': [],
'uva': [],
'uvb': [],
'uvc': [],
'light': [],
'heat': []
}

try:
with open(LOG_FILE, 'r') as f:
reader = csv.reader(f)
for row in reader:
try:
print(row[0],row[1])
timestamp = datetime.strptime(row[0] + "." + row[1], '%Y-%m-%d %H:%M:%S.%f')
data['timestamps'].append(timestamp.strftime('%Y-%m-%d %H:%M'))
data['temperature'].append(float(row[2]))
data['humidity'].append(float(row[3]))
data['uva'].append(float(row[4]))
data['uvb'].append(float(row[5]))
data['uvc'].append(float(row[6]))
data['light'].append(int(row[7]))
data['heat'].append(int(row[8]))
except (ValueError, IndexError) as e:
print(e)
continue
except FileNotFoundError:
print(f"{LOG_FILE} not found")
pass

return data

@app.route('/')
def index():
"""Render the main page"""
config = read_config()
return render_template('index.html', config=config)

@app.route('/api/config', methods=['GET'])
def get_config():
"""Get current configuration"""
return jsonify(read_config())

@app.route('/api/config', methods=['POST'])
def update_config():
"""Update configuration"""
try:
new_config = request.get_json()
write_config(new_config)
# Restart the gecko-controller service to apply changes
os.system('systemctl restart gecko-controller')
return jsonify({'status': 'success'})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 400

@app.route('/api/logs')
def get_logs():
"""Get log data"""
hours = request.args.get('hours', default=24, type=int)
return jsonify(read_logs(hours))

def main():
app.run(host='0.0.0.0', port=8080)

if __name__ == '__main__':
main()
Loading

0 comments on commit d1ca84a

Please sign in to comment.