Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for a 3.5 inch display. #25

Open
GamingDaveUk opened this issue Nov 27, 2023 · 2 comments
Open

support for a 3.5 inch display. #25

GamingDaveUk opened this issue Nov 27, 2023 · 2 comments

Comments

@GamingDaveUk
Copy link

Is your feature request related to a problem? Please describe.
I just purchased a 3.5inch display for a pi 2 model b to display the curerent half hour rate - upcoming rate - current consumption (if the api supports it) - consumption so far on that day (and price....)
The idea was to replace my smart meters out of date monitor that cant show anything beyond current consumption lol

Then I realised I dont know how to do any of that and google lead me here.

Describe the solution you'd like
I would love to be able to display the text like you have it but on a self updating local website hosted on the PI, displayed on the 3.5 inch display. Not sure if such is possible.

Describe alternatives you've considered
sitting in the corner and rocking back and forward slowly.
learning python and how to make a website thats dynamic using python...thats actually a long term thing.
Additional context
I know c#, would be happy to be shown how to get a specific value for the half hour time slot via the api and have it in a variable then pointed in the direction of how to make a website with python that displays that variable on it.... armed with that knowledge i could probably extrapolate the rest.... but i dont know where to begin lol

Your app fills a mysql database, so knowing how to pull a value from that data base and a link to a good noob friendly python website building guide could be all I need?

@GamingDaveUk
Copy link
Author

GamingDaveUk commented Nov 28, 2023

Not one to sit idle and wait for solutions to land on my lap i set about working out how to do this. Aided massively (and hindered by) ChatGPT.

I broke the problem down into several parts. I needed the site to autoupdate on recieving new data (as the site is what will be on my display) and i needed a way to parse the data from the api curl grab.

The scripts are stored in a folder and the webpage is stored in a templates folder in that folder... it makes sense when you look at the code.

The website:
`

<title>Rate Update</title>

Current rate:

Next rate:

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/socket.io.js"></script>
<script>
    var socket = io.connect('http://' + document.domain + ':' + location.port);

    socket.on('connect', function() {
        console.log('Connected to server');
    });

    socket.on('update', function(data) {
        document.getElementById('current-rate').innerText = data.current_rate;
        document.getElementById('next-rate').innerText = data.next_rate;

        // Save the most recent values to local storage
        localStorage.setItem('currentRate', data.current_rate);
        localStorage.setItem('nextRate', data.next_rate);
    });

    // Retrieve and display the most recent values from local storage
    var storedCurrentRate = localStorage.getItem('currentRate');
    var storedNextRate = localStorage.getItem('nextRate');

    if (storedCurrentRate) {
        document.getElementById('current-rate').innerText = storedCurrentRate;
    }

    if (storedNextRate) {
        document.getElementById('next-rate').innerText = storedNextRate;
    }
</script>
`

The server.py (this needs to be running all the time.
`from flask import Flask, render_template
from flask_socketio import SocketIO, emit

app = Flask(name)
socketio = SocketIO(app, async_mode='eventlet')

current_rate = "Initial Current Rate"
next_rate = "Initial Next Rate"

@app.route('/')
def index():
return render_template('index.html', current_rate=current_rate, next_rate=next_rate)

Modify the 'update_rates' event to 'update' in server.py

@socketio.on('update_rates')
def handle_update_rates(data):
global current_rate, next_rate
current_rate = data['current_rate']
next_rate = data['next_rate']
emit('update', {'current_rate': current_rate, 'next_rate': next_rate}, broadcast=True)
print('Emitted update event:', {'current_rate': 99, 'next_rate': 88})

if name == 'main':
socketio.run(app, debug=True, host='0.0.0.0')

@socketio.on('connect')
def handle_connect():
print('Client connected')

@sio.on('disconnect')
def on_disconnect():
print('Disconnected from server')
`

The client.py... this is what i plan to run via cron every 30 minutes.
`import socketio
import time
import json
from datetime import datetime, timedelta

sio = socketio.Client()
json_file_path = 'data.json'
current_datetime = datetime.now()

@sio.on('connect')

def on_connect():
print('Connected to server')

def get_current_value_inc_vat(json_file_path):
# Load JSON data from the file
with open(json_file_path, 'r') as file:
data = json.load(file)

# Get the current date and time
#current_datetime = datetime.now()

# Iterate through the "results" list to find the corresponding "value_inc_vat"
for result in data['results']:
    valid_from = datetime.strptime(result['valid_from'], "%Y-%m-%dT%H:%M:%SZ")
    valid_to = datetime.strptime(result['valid_to'], "%Y-%m-%dT%H:%M:%SZ")

    # Check if the current time is within the valid range
    if valid_from <= current_datetime <= valid_to:
        return result['value_inc_vat']

# If no matching time range is found, return None or an appropriate value
return None

def get_value_at_future_time(json_file_path, minutes_offset=0):
# Load JSON data from the file
with open(json_file_path, 'r') as file:
data = json.load(file)

# Get the current date and time
#current_datetime = datetime.now()

# Calculate the future time by adding the specified offset (in minutes)
future_datetime = current_datetime + timedelta(minutes=minutes_offset)
    # Iterate through the "results" list to find the corresponding value at the future time
for result in data['results']:
    valid_from = datetime.strptime(result['valid_from'], "%Y-%m-%dT%H:%M:%SZ")
    valid_to = datetime.strptime(result['valid_to'], "%Y-%m-%dT%H:%M:%SZ")

    # Check if the future time is within the valid range
    if valid_from <= future_datetime <= valid_to:
        return result['value_inc_vat']

# If no matching time range is found, return None or an appropriate value
return None

def update_rates(current_rate, next_rate):
sio.emit('update_rates', {'current_rate': current_rate, 'next_rate': next_rate})
print('Sent update_rates event to server')
print(f"current rate: {current_rate} - next rate: {next_rate}")

if name == 'main':
try:
sio.connect('http://localhost:5000') # Adjust the server URL as needed

    # Update the rates here
    current_rate = get_current_value_inc_vat(json_file_path)
    next_rate = get_value_at_future_time(json_file_path, minutes_offset=30)

    # Send the updated rates to the server
    update_rates(current_rate, next_rate)

except KeyboardInterrupt:
    print("Client closed by the user.")

`

The data.json is in the same folder as the scripts and contains the out put of the curl command to get the rates. bit too long to add here but its the result of the curl command from Unit rates on https://octopus.energy/dashboard/new/accounts/personal-details/api-access

I still need to write a script that will run that curl command at 1600 and replace the existing data.json file...but i feel that should be simple enough.
There are also a lot of pip install modules that are needed for this which i didnt document. posting this as i hate leaving a question with "done" or "fixed it" I doubt me and chatgpt came up with the best way... but it works.... most of the time....it did seem to strugle to update the site then suddenly it updated it, The web page needs to be full screened on the tft display and I likely need to find some code to move the text about to prevent burn in.

I initially tried to host the page seperate from the script but that proved to be a pain from a sockets point of view. I havent looked at pulling current usage or the daily consumption yet, not sure thats possible with the api. Interesting experiement though and something i plan to look more at with time

EDIT: i put the files in code togs for github...it doesnt seem to have liked that. but anyone trying to repeat what i did should be able to decode these lol

@GamingDaveUk
Copy link
Author

I wasnt happy with how the text got mangled above so I created a repo for what I was doing. This includes the .sh for retrieving the prices too
no readme yet, I need to have some time to write that.
https://github.com/GamingDaveUk/OctopusAgileRatePage

I have no idea if this is even remotely helpful to others though lol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant