Kotinäyttö VANHA VERSIO
PenaPedia
Löysin sittenkin sattumalta vanhan version. Huhhuh, otetaan sekin nyt esille tänne.
En tiedä toimiiko se suoriltaan ja miten hyvin mutta lähinnä tuon muuttuvan liittymätehon palkin kaipasin mielelläni takaisin, koska siinä olikin hieman pähkäilyä.
Jatkamme silti uuden kehittämistä, tästä saadaan vain hyvää mallia jos tarvitsee luntata. Rakenteellisesti tuo on aivan hirveä eikä sitä kannata käyttää kuin korkeintaan viitteellisenä mallina
- Sähkön hinnan haku ei ainakaan toimi, vaan jos sellaista tarvii, tulee käyttää myöhemmin julkaistavan kunnollisen version funktioita
Kotinäyttö
Pääsivu, täällä jalostetaan uusinta versiota.
PALVELINPUOLI
import RPi.GPIO as GPIO import time, sys import http.server from http.server import BaseHTTPRequestHandler, HTTPServer import socketserver import _thread import threading import socket from socketserver import ThreadingMixIn import requests, json import datetime import array as arr import statistics import time import json import pprint import math import os import ADS1x15 from timeit import Timer from numpy import log as ln from urllib.parse import unquote paivaHinta = 4.08 + ((2.79372 + 0.22) * 1.24) yoHinta = 2.67 + ((2.79372 + 0.22) * 1.24) varaajan_last_timestamp = 0 sahkonKiinteaOsa = {toFixed 0 : yoHinta, 1 : yoHinta, 2 : yoHinta, 3 : yoHinta, 4 : yoHinta, 5 : yoHinta, 6 : yoHinta, 7 : paivaHinta, 8 : paivaHinta, 9 : paivaHinta, 10: paivaHinta, 11: paivaHinta, 12: paivaHinta, 13: paivaHinta, 14: paivaHinta, 15: paivaHinta, 16: paivaHinta, 17: paivaHinta, 18: paivaHinta, 19: paivaHinta, 20: paivaHinta, 21: paivaHinta, 22: yoHinta, 23: yoHinta } data = { 'sahko_hinta_tanaan' : [0 for i in range(25)] , 'sahko_hinta_huomenna' : [0 for i in range(25)] , 'kulutus_spot' : [0], 'spot_kulutus_hinta' : [0], 'kumul_spot_kokonaishinta' : 0, 'kumul_kokonaiskulutus' : 0, 'kumul_pulssit' : 0, 'elspot_alv' : 1.24, #HOX Nordpoolin hinnat ovat verottomia. HOX ALV lasketaan verottomasta hinnasta ;) 'elspot_marginaali' : 0.01, 'piirturi_sahko' : [0], 'piirturi_pulssit' : 0, 'piirturi_count' : 1000, #Piirturi aloittaa seuraavasta tasa-vartista 'siirtoHintaYosahkolla' : 0, 'varaajan_kayntitunnit' : [0], 'currentHour' : 0, 'sahko' : {'pulsseja_laskettu' : 0, 'pulssien_vali' : 10, 'pulssien_otanta' : 5, 'realTimeMonitorLog' : [0], 'pulssit_yo' : 0, 'pulssit_paiva' : 0, 'lastTimestamp' : 0, 'pulsseja_per_kwh' : 10000, # yes, Mäntsälän Sähkö aivilon have 10 000 blinks per kWh ;) 'kulutusTunneittain' : [0 for i in range(24)], 'hintaTunneittain' : [0 for i in range(24)], 'varaajan_tarve' : [0] }, 'kv' : {'pulsseja_laskettu' : 0, #Täysin turha homma mutta en mene nyt sorkkimaan sitä 'vetta_kulunut' : 0, 'pulssien_vali' : 0 }, 'meta' : {'saikeitaKaynnissa' : 0, 'asiakkaitaPaikalla': 0, 'data_tumple_size' : 44, #Mikshän tuo on noin ?? Kysyisin itseltäin 'broadcastedBytes' : 0, 'nordpoolReqTimes' : 0, 'httpPyyntojaSaatu' : 0, 'allowNordpoolReq' : 1, #Vahditaan hieman ettei ala spämmiä Nordpooliin. Kerran jo pelastikin kun tein virheen koodiin 'paivamaaraTanaan' : datetime.datetime.today().strftime("%d-%m-%Y"), 'restartTimes' : 0, 'ajoaikaSec' : 0, 'tuntilaskuri' : 0, 'datadumppiLuotu' : time.time() }, 'vesi' : {'taajuus' : 0, 'lastTimestamp' : 0, 'ulkokierto_count' : 0, 'kierron_lammitysteho' : 0, 'kierron_saasto' : 0, 'kylma_vesi_c' : 5, #kaivoveden lämpötila, lämmitystehon laskua varten TÄTÄ ARVOA EI VOI MUUTTAA JÄLKEENPÄIN, ei vaikuta takautuvasti lukemiin TODO: Hommaa mittari tohon 'kylma_vesi_taajuus' : 0, 'kylma_vesi_lastTimestamp' : 0, 'kylma_vesi_count' : 0, 'varaajan_kapasiteetti' : 99000, # 99000 pulssia mittarilta = 150 litraa, 'varaajan_havioteho' : 0.1, # kW 'varaajan_lammitysteho' : 1.92, # kW 'varaajan_status' : 99000, # Lähtötilanne = täynnä 'varaajan_status_esilam' : 99000, # Varaajan latausaste lasketaan myös huomioiden veden esilämmitys 'varaajan_pakotus' : False # True = pinout lähtö on silloin 0, avautuva kosketin ohjaa kontaktorin kelaa }, 'vesi_logi': { 'kylma_paivittain' : [0], #HOX tätä ei striimata livenä, eritelty siksi veden alaisuudesta pois 'lammin_paivittain' : [0], 'ponton_lampotila' : [0], 'kierron_menolampo' : [0], 'kierron_paluulampo' : [0] }, 'ilp': { 'ilp_count_per_h' : [0], 'ilp_count' : 0, 'ilp_teho' : 0, 'ilp_delay' : 0, 'ulkolampo' : [0], # Näiden logituksen pituudesta päättää siivooja() 'sisalampo' : [0], 'parvi' : [0], 'sisa_puhallus' : [0], 'ilp_ottoteho_log' : [0], 'wc_lampo' : [0], 'varaajain_lampo' : [0], 'lastTimestamp' : 0, 'tuuletin_auto' : 0, 'tuuletin_pwm' : 0, 'tuuletin_parametrit' : 'sp1_c=1 sp1_kW=0.3 sp2_c=2 sp2_kW=0.7 poissa=0 ' }, 'lastLogs' : [0] } #Tossa on niin vitusti kaikkea turhaa etten ole edes itsekään enään perillä kaikesta # Vesimittarien kertoimet 1/2 = 11 ja 3/4 = 6.6 devices = { 'huone' : '/sys/bus/w1/devices/28-3cf5f648648b/w1_slave', 'parvi' : '/sys/bus/w1/devices/28-3c05f6482521/w1_slave', 'ulko' : '/sys/bus/w1/devices/28-3c03f648e6af/w1_slave', 'sisa_puhallus' : '/sys/bus/w1/devices/28-3ca9f648c262/w1_slave', 'kierron_meno' : '/sys/bus/w1/devices/28-3ce10457c47b/w1_slave', 'kierron_paluu' : '/sys/bus/w1/devices/28-3ce1045723c3/w1_slave', 'ponton_lampotila' : '/sys/bus/w1/devices/28-3ce10457e032/w1_slave' } ilpOttotehoAwg = [1] def varaajan_hoitaja(): global data varaajan_hallinta('varaaja_paalle') return 0 #hinnat_tanaan = hae_sahkonhinta() hinnat_tanaan = data['sahko_hinta_tanaan'] tunti = int(((datetime.datetime.today()).strftime('%-H'))) kaytettavatHinnat = [] #Kopioidaan taulukko, otetaan huomioon vain tästä tunnista eteenpäin hinnat,viimeinen indeksi on pvm sitä ei otetea kaytettavatHinnat = data['sahko_hinta_tanaan'][tunti:-1].copy() print(type(kaytettavatHinnat)) print(type(data['sahko_hinta_huomenna'])) #Onko huomisen hintoja vielä tullut if data['sahko_hinta_huomenna'][0] != 0: hinnat_huomenna = data['sahko_hinta_huomenna'][-2] kaytettavatHinnat.append(hinnat_huomenna) print(data['sahko_hinta_huomenna']) print("TUNTI NAYTTAA: " + str(tunti)) summaaja = 0 #my_list = [float(i) for i in my_list] ka = math.fsum(map(float, kaytettavatHinnat)) / len(kaytettavatHinnat)#Keskiarvo kaikista tulevista hinnoista #Muutetaan varaajan kapasiteetti ja latausaste kilowateiksi: data['sahko']['varaajan_tarve'] = ((data['vesi']['varaajan_kapasiteetti'] / 60 / 11) * 80 * 4.2) / 3600 - ((data['vesi']['varaajan_status'] / 60 / 11) * 80 * 4.2) / 3600 logi("Varaajan lämmitystarve: " + str(data['sahko']['varaajan_tarve'])) #Käyntitunnit kerrotaan lämmitysteholla, jotta saadaan oikea lukema esim. 2 kW teholla tunnissa varaaja latautuu 2 kW/h kayntitunnit = [] print("KÄYTETTÄVÄT HINNAT: " + str(kaytettavatHinnat)) #Lasketaan montako tuntia voidaan pitää varaajaa päällä raaoilla hintarajoilla #Esim aina päällä jos kokonaishinta on alle 10 cnt for i in range(len(kaytettavatHinnat)): if kaytettavatHinnat[i] < 8.5: print("Päällä: tunti = " + str(i + tunti) + " hinnalla: " + str(kaytettavatHinnat[i])) kayntitunnit.append((tunti + i)) continue if kaytettavatHinnat[i] < min(kaytettavatHinnat) * 1.15: print("Päällä: tunti = " + str(i + tunti) + " hinnalla: " + str(kaytettavatHinnat[i])) kayntitunnit.append((tunti + i)) continue #Toinen kierros, sallitaan kalliimpia hintoja jos varaajan kilowattitarve on kasvanut for i in range(len(kaytettavatHinnat)): if (tunti + i) in kayntitunnit: #Skippaa tunnit jotka on jo raaoilla arvoilla #print("Skipataan tunti: " + str(i)) i = i+1 continue #Jos varaajan lämmöntarve on suurempi kuin hinnaston ka. sallitaan lämmitystunti #hinnalla joka on max. 50 % kaikkien hintojen keskiarvosta if (len(kayntitunnit) * data['vesi']['varaajan_lammitysteho'] ) < data['sahko']['varaajan_tarve'] and kaytettavatHinnat[i] < ka * 0.3: print("min + 30 % tunti = " + str(i) + " hinnalla: " + str(kaytettavatHinnat[tunti + i])) kayntitunnit.append(i + tunti) continue if (len(kayntitunnit) * data['vesi']['varaajan_lammitysteho'] ) < data['sahko']['varaajan_tarve'] and kaytettavatHinnat[i] < ka * 0.5: print("min + 50 % tunti = " + str(i) + " hinnalla: " + str(kaytettavatHinnat[int(tunti + i)])) kayntitunnit.append(i + tunti) continue #Jos ei edellinenkään riitä, sallitaan varaajan käynnistyä max. keskiarvon hintaisilla tunneilla if (len(kayntitunnit) * data['vesi']['varaajan_lammitysteho'] ) < data['sahko']['varaajan_tarve'] and kaytettavatHinnat[i] < ka: print("KA hinnalla: tunti = " + str(tunti + i) + " hinnalla: " + str(kaytettavatHinnat[int(tunti + i)])) kayntitunnit.append(i + tunti) continue if (len(kayntitunnit) * data['vesi']['varaajan_lammitysteho'] ) < data['sahko']['varaajan_tarve'] and kaytettavatHinnat[i] < ka * 1.2: print("KA + 20% tunti = " + str(tunti + i) + " hinnalla: " + str(kaytettavatHinnat[int(tunti + i)])) kayntitunnit.append(i + tunti) continue if data['vesi']['varaajan_pakotus'] == True: logi("Varaajan hoitaja kirjaa tämän tunnin päällepakotetuksi") kayntitunnit.append(tunti) logi("Varaajan hoitaja kirjasi tunti nro: " + str(tunti) + " päällepakotetuksi") logi(str(kaytettavatHinnat)) data['varaajan_kayntitunnit'] = kayntitunnit def varaajan_hallinta(arg): global data, varaajan_last_timestamp #Aina pitää olla kulunut 60 * 2 sekunttia ennen kuin varaajan kärkitilaa voi muuttaa if arg == 'varaaja_paalle' and (time.time() - varaajan_last_timestamp) > 60 * 2: varaajan_last_timestamp = time.time() logi("Varaaja käynnistettiin!") GPIO.output(25, 1) return 0 return 0 if arg == 'sammuta_varaaja' and (time.time() - varaajan_last_timestamp) > 60 * 2: varaajan_last_timestamp = time.time() GPIO.output(25, 0) logi("Varaaja sammutettiin!") return 0 logi("***** VARAAJAN HALLINNAN KUMPIKAAN EHTO EI TOTEUTUNUT ******") logi("AIKA-ARVO: " + str(time.time() - varaajan_last_timestamp)) logi("***************") def parsi_lampotila(lines): #Palauttaa arvon 0, jos lämpöä ei mistä tahansa syystä saada if lines == False or len(lines) != 2: ##logi("parsi_lampotila: EI PARSITTAVAA") print(lines) return 0 logi("parsi_lampotila() : " + str(lines)) if (lines[0][-4 : len(lines[0])-1]) != 'YES': logi("parsi_lampotila: TEMP IS NOT VALID") logi("txt") return 0 #print(lines[0][-3 : len(lines[0])]) return round(int(lines[1][lines[1].find("t=")+2:len(lines[1])]) / 1000, 1) def lue_anturi (device): ##logi("AVATAAN LAITE: " + device) time.sleep(1) try: with open(device, 'r') as onewire: time.sleep(0.5) lines = onewire.readlines() onewire.close() except: logi("lue_anturi: EI LÖYDY LAITETIEDOSTOA") logi("lue_anturi: " + device) time.sleep(1) return parsi_lampotila(False) return parsi_lampotila(lines) def tuulettimen_ohjaus(): #data['ilp']['tuuletin_parametrit'] = 'sp1_c=1 sp1_kW=0.3 sp2_c=3 sp2_kW=0.7' logi("Tuulettimen parametrit: " + data['ilp']['tuuletin_parametrit']) nopeudet = (dict(s.split('=', 1) for s in data['ilp']['tuuletin_parametrit'].split())) lampotilaero = data['ilp']['parvi'][-1] - data['ilp']['sisalampo'][-1] logi("Lampotilaero: " + str(lampotilaero)) if int(nopeudet['poissa']) == 1: GPIO.output(21, 1) GPIO.output(20, 0) logi("Puhaltimen pieni nopeus - poissa = 1") return 0 if lampotilaero > float(nopeudet['sp2_c']) or data['ilp']['ilp_teho'] > float(nopeudet['sp2_kW']): #Suurin nopeus GPIO.output(21, 0) time.sleep(1) GPIO.output(21, 1) GPIO.output(20, 1) logi("Puhaltimen suuri nopeus") return 0 if lampotilaero > float(nopeudet['sp1_c']) or data['ilp']['ilp_teho'] > float(nopeudet['sp1_kW']): #Toisiksi suurin nopeus GPIO.output(21, 1) GPIO.output(20, 0) logi("Puhaltimen pieni nopeus") return 0 GPIO.output(21, 0) #Puhallin kiinni, jos päästään tänne asti logi("GPIO: 21 = 0, puhallin kiinni") return 0 def siivooja(): #Poistetaan tarpeeksi vanhat lukemat global data if len(data['ilp']['sisalampo']) > 1440: #1440 min == 24 h data['ilp']['sisalampo'].pop(0) if len(data['ilp']['ulkolampo']) > 1440: data['ilp']['ulkolampo'].pop(0) if len(data['ilp']['parvi']) > 1440: data['ilp']['parvi'].pop(0) if len(data['ilp']['sisa_puhallus']) > 1440: data['ilp']['sisa_puhallus'].pop(0) if len(data['ilp']['ilp_ottoteho_log']) > 1440: data['ilp']['ilp_ottoteho_log'].pop(0) if len(data['lastLogs']) > 20: #Rivien määrä data['lastLogs'].pop(0) if len(data['kulutus_spot']) > 48: #Sähkön kulutus, tunneittain data['kulutus_spot'].pop(0) if len(data['ilp']['ilp_count_per_h']) > 24*7*31: #ILP kulutus, tunneittain data['ilp']['ilp_count_per_h'].pop(0) if len(data['sahko']['realTimeMonitorLog']) > 50: #Hetkellinen kulutus, rivien määrä data['sahko']['realTimeMonitorLog'].pop(0) if len(data['vesi_logi']['kierron_paluulampo']) > 1440: data['vesi_logi']['kierron_paluulampo'].pop(0) if len(data['vesi_logi']['ponton_lampotila']) > 1440: data['vesi_logi']['ponton_lampotila'].pop(0) if len(data['vesi_logi']['kierron_menolampo']) > 1440: data['vesi_logi']['kierron_menolampo'].pop(0) class handler(BaseHTTPRequestHandler): global tuloste def do_OPTIONS(self): self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") #self.send_header("Access-Control-Allow-Credentials", "true") self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') self.send_header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept") self.end_headers() def do_GET(self): data['meta']['httpPyyntojaSaatu'] += 1 logi("GEttiä kutsutaan!") if '?tuuletin_parametrit' in self.path: data['ilp']['tuuletin_parametrit'] = unquote(self.path.split('?tuuletin_parametrit')[1]) logi("Uudet parametrit: " + data['ilp']['tuuletin_parametrit']) if self.path.endswith('/kaikki_data'): #Lähettää koko data arrayn json dumppina self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") #self.send_header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Origin, Accept") self.send_header('Content-type', 'application/json') self.end_headers() output = str.encode(json.dumps(data)) data['meta']['broadcastedBytes'] += len(output) self.wfile.write(output) logi("/kaikki_data tarjoiltu") return logi("yhteys ei katkea") elif self.path.endswith('/debug'): self.send_response(200) self.send_header('Content-type', 'text/plain') self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() output = "" output += pprint.pformat(data, indent=1,sort_dicts=False) #Prints multidimensional array or list very very pretty - with tabs and <br>s on browser. Fucking hard find this on simple without anything functions or loops self.wfile.write(str.encode(output)) return elif self.path.endswith('/pakota_varaaja_paalle'): self.send_response(200) self.send_header('Content-type', 'text/plain') self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() if data['vesi']['varaajan_pakotus'] == False: data['vesi']['varaajan_pakotus'] = True else: data['vesi']['varaajan_pakotus'] = False return elif self.path.endswith('/etusivu.html'): self.send_response(200) self.send_header('Content-type', 'text/html; charset=UTF-8') self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() f = open("etusivu.html", "r") output = f.read() f.close() data['meta']['broadcastedBytes'] += len(output) self.wfile.write(str.encode(output)) return elif self.path.endswith('/livestream'): data['meta']['asiakkaitaPaikalla'] += 1 #Soketti pidetään auki jatkuvasti ja lähetetään selaimelle SSE tyylillä *** MUISTA ALKUUN 'data: ' teksti ja loppuun KAKSI rivinvaihtoa self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") #self.send_header("Access-Control-Allow-Credentials", "true") self.send_header('Cache-Control:', 'no-cache') self.send_header('Content-type', 'text/event-stream') self.end_headers() edellinen_lastLog = 0 lastHourDateTime = int(((datetime.datetime.today()-datetime.timedelta(hours = 1)).strftime('%-H'))) while True: #Valikoitua dataa lähetetään sekunnin välein selaimelle lastLog = 0 if data['lastLogs'][len(data['lastLogs']) - 1] != edellinen_lastLog: #Ei lähetetä samaa lastlogia uudestaan lastLog = data['lastLogs'][len(data['lastLogs']) - 1] edellinen_lastLog = data['lastLogs'][len(data['lastLogs']) - 1] tunti = int(((datetime.datetime.today()).strftime('%-H'))) output = ('data: ' + json.dumps({ 'realTimeMonitorLog' : data['sahko']['realTimeMonitorLog'][ len(data['sahko']['realTimeMonitorLog']) - 1 ], 'meta' : data['meta'], 'lastLogs' : lastLog, 'pulsseja_laskettu' : sum(data['sahko']['kulutusTunneittain']), 'kumul_spot_kokonaishinta' : data['kumul_spot_kokonaishinta'] + (data['piirturi_pulssit'] * ( 1 / data['sahko']['pulsseja_per_kwh'])) * data['sahko_hinta_tanaan'][tunti], 'vesi' : data['vesi'], 'ilp_count' : data['ilp']['ilp_count'] + sum(data['ilp']['ilp_count_per_h']), 'ilp_teho' : data['ilp']['ilp_teho'], 'ulkolampo' : data['ilp']['ulkolampo'][-1], 'sisalampo' : data['ilp']['sisalampo'][-1], 'parvi' : data['ilp']['parvi'][-1], 'sisa_puhallus' : data['ilp']['sisa_puhallus'][-1], 'varaajan_karkitieto' : int(GPIO.input(25)), #Varaaja sammuu, kun relepaketti vetää 'pulssit_paiva' : data['sahko']['pulssit_paiva'], 'pulssit_yo' : data['sahko']['pulssit_yo'], 'piirturi_pulssit' : data['piirturi_pulssit'], 'sahkon_hinta_nyt' : data['sahko_hinta_tanaan'][tunti], 'kuluva_tunti' : tunti, 'vesi_ulkokierto_meno' : data['vesi_logi']['kierron_menolampo'][-1], 'vesi_ulkokierto_tmp' : data['vesi_logi']['kierron_paluulampo'][-1], 'vesi_ponton_tmp' : data['vesi_logi']['ponton_lampotila'][-1] }) + "\n\n") output = str.encode(output) data['meta']['broadcastedBytes'] += len(output) try: self.wfile.write(output) except: logi("SOKETTI TAISI KATKETA") data['meta']['asiakkaitaPaikalla'] -= 1 return #print(output) time.sleep(1) logi("YHTEYS KATKESI") else: self.send_response(404) #self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() output = "<h1>ETUSIVU</h1>" self.wfile.write(str.encode(output)) print("TÄnne ei pitäisi päästä") #Joskus tänne pääsee silti :O def kodin_hengetar(): logi("Kodin hengetär täällä!") global data, f, devices, ilpOttotehoAwg #testi = 0 ulkokierto_count_temp = 0 kierronSaastoTemp = time.time() #TÄMÄ RIVI ON VAIN MUUTTUJAN KERTALUONTEINEN ALUSTUS #print(data['sahkon_hinta_tanaan']) while True: ulkokierto_count_temp = data['vesi']['ulkokierto_count'] # Heti alussa talteen nykyhetken mittarilukema pysayta_mittari() time.sleep(1) #data['meta']['paivamaaraTanaan'] = datetime.datetime.today().strftime("%d-%m-%Y") data['meta']['data_tumple_size'] = sys.getsizeof(data) if data['meta']['paivamaaraTanaan'] != datetime.datetime.today().strftime("%d-%m-%Y"): #testi = 0 logi("PAIVA VAIHTUI") data['vesi_logi']['kylma_paivittain'].append((data['vesi']['kylma_vesi_count'] / 6.6) / 60) data['vesi']['kylma_vesi_count'] = 0 data['vesi_logi']['lammin_paivittain'].append((data['vesi']['ulkokierto_count'] / 11) / 60) data['vesi']['ulkokierto_count'] = 0 data['meta']['paivamaaraTanaan'] = datetime.datetime.today().strftime("%d-%m-%Y") #testi += 1 if data['meta']['nordpoolReqTimes'] > 500: #Turvafeature, ettei syystä tai toisesta virhetilanteessa ala mennä spämmiä nordpooliin pyyntöjä data['meta']['allowNordpoolReq'] = 0 logi("NORDPOOL = 0") return 0 if data['sahko_hinta_tanaan'][24] != datetime.datetime.today().strftime('%d-%m-%Y') and data['meta']['allowNordpoolReq'] == 1: #Viimeinen indeksi on päivämäärä ^^ logi("Haetaan tämän päivän sähkön hinta (sahkon_hinta_tanaan 24 = " + str(data['sahko_hinta_tanaan'][24])) data['sahko_hinta_tanaan'] = hae_sahkonhinta(data['meta']['paivamaaraTanaan']).copy() logi("Haettiin tämän päivän sähkönhinta") logi(data['sahko_hinta_tanaan'][24]) data['sahko_hinta_huomenna'] = [0 for i in range(25)] huominen = (datetime.datetime.today()+datetime.timedelta(days=+1)).strftime('%d-%m-%Y') if data['sahko_hinta_huomenna'][24] != huominen and int(time.strftime("%H")) > 14 and data['meta']['allowNordpoolReq'] == 1: logi("Haetaan huomisen sähkön hinnat:") data['sahko_hinta_huomenna'] = hae_sahkonhinta(huominen).copy() logi("HAETTIIN HUOMISEN HINNAT") data['meta']['saikeitaKaynnissa'] = threading.active_count() laske_sahkon_kulutus() ilpOttotehoAwg.append(data['ilp']['ilp_teho']) #Joka sekuntti lisätään sen hetken spot teho if len(ilpOttotehoAwg) > 60: #Pidetään n. minuutin mittaista rullaavaa listaa ilpOttotehoAwg.pop(0) #data['vesi']['kierron_paluulampo'] = mittaa_lampotila() #data['vesi']['kierron_lammitysteho'] = (((data['vesi']['taajuus'] / 11)/60) * (data['vesi']['kierron_paluulampo'] - data['vesi']['kylma_vesi_c']) * 4.2) #4.2 = veden ominaislämpökapasiteetti #Kaava benchmnarkattu ^^ ##### VARAAJAN HOITO #### data['vesi']['varaajan_status'] -= data['vesi']['ulkokierto_count'] - ulkokierto_count_temp # Vähennetään varaajan statuksesta kierroksen aikana käytetty vesimäärä if data['vesi']['varaajan_status'] > data['vesi']['varaajan_kapasiteetti']: # Varaaja on täynnä, tämä ettei varaajan_status ylitäyty data['vesi']['varaajan_status'] = data['vesi']['varaajan_kapasiteetti'] logi("Varaaja on täynnä") if (data['vesi']['varaajan_status'] < 500): #Varaajan status ei voi mennä nollaan tai negatiiviseksi logi("Varaajan_status lähestyy nollaa!") logi("Muutetaan statukseksi 5000") data['vesi']['varaajan_status'] = 5000 #data['vesi']['kierron_saasto'] += (data['vesi']['kierron_lammitysteho'] / (3600 / (time.time() - kierronSaastoTemp))) siivooja() kierronSaastoTemp = time.time() #Tästä saadaan aika kauanko yhteen kierrokseen menee (sek) TÄMÄN PITÄÄ OLLA VIIMEISENÄ logi("Kodin hengetär loppu") def hearthbeat(): #Kutsutaan kerran minuutissa tekemään jotain hanttihommia global data, devices, ilpOttotehoAwg #if int(((datetime.datetime.today()).strftime('%S'))) % 60 == 0: offset_aika = time.time() odotusaika = 60 if 1: logi(" *** Hearthbeat ***") #logi("LUETAAN HUONE:") data['ilp']['sisalampo'].append(lue_anturi(devices['huone'])) #logi("LUETAAN ULKO:") data['ilp']['ulkolampo'].append(lue_anturi(devices['ulko'])) #logi("LUETAAN PARVI: ") data['ilp']['parvi'].append(lue_anturi(devices['parvi'])) #logi("LUETAAN SISA_PUHALLUS: ") data['ilp']['sisa_puhallus'].append(lue_anturi(devices['sisa_puhallus'])) data['vesi_logi']['kierron_paluulampo'].append(lue_anturi(devices['kierron_paluu'])) data['vesi_logi']['ponton_lampotila'].append(lue_anturi(devices['ponton_lampotila'])) data['vesi_logi']['kierron_menolampo'].append(lue_anturi(devices['kierron_meno'])) #Käynnistyksessä kaatuu, kun tapahtuu nollalla jako ilman tätä ehtoa data['ilp']['ilp_ottoteho_log'].append(float(f"{sum(ilpOttotehoAwg) / len(ilpOttotehoAwg):.3f}")) #keskiarvo sekunneittain mitatusta ottotehosta ###VARAAJA / MINUUTEITTAIN TEHTÄVÄT TOIMET #### #Pakotusta ei laiteta päälle automaattisesti tyhjentyessä, jos varaaja on jo - syystä tai toisesta valmiiksi päällä if (data['vesi']['varaajan_status'] / data['vesi']['varaajan_kapasiteetti']) * 100 < 15 and GPIO.input(25) == 0: data['vesi']['varaajan_pakotus'] = True logi("Varaajan päällepakotusehto täyttyi!") if data['vesi']['varaajan_pakotus'] == True: # Jos varaaja on pakotettu päälle varaajan_hallinta("varaaja_paalle") logi("Varaaja on pakotettuna päälle") time.sleep(1) if GPIO.input(25) == 1: #Lisätään lämpöä vain, jos varaajan kela vetää. Tämä ehto toimii irrallaan kaikesta muusta heatDiff = 85 - data['vesi']['kylma_vesi_c'] #Veden lämpötilan nousun määrä asteina kaivokylmästä heatPulsesPerMin = ((data['vesi']['varaajan_lammitysteho'] * 60) / heatDiff / 4.2) * 11 * 60 #Muunnos (kW --> Wh) / montako pulssia X lämpöistä vettä tulee Y teholla 60 sek aikana data['vesi']['varaajan_status'] += heatPulsesPerMin #Lisätään varaajaan lämmintä #Varaajasta poistetaan aina häviö, tilasta riippumatta, ennalta määritetyllä teholla: data['vesi']['varaajan_status'] -= ((data['vesi']['varaajan_havioteho'] * 60) / (85 - 20) / 4.2) * 11 * 60 #Häviöteho, montako litraa lämmitetään 85 - huonelämpö, minuutin aikana X teholla #Montako pulssia (litraa) status laskee X häviöteholla, lämpötilaeron ollessa Y #Memo: ajattele asiaa näin: "montako litraa vettä lämpenee esim. 60 astetta tietyllä teholla MINUUTIN AIKANA" --> saat litramäärän --> muuta se vielä pulssien lukumääräksi vesimittarin kertoimella (11) data['vesi']['varaajan_status_esilam'] -= ((data['vesi']['varaajan_havioteho'] * 60) / (85 - 20) / 4.2) * 11 * 60 #Häviöteho, montako litraa lämmitetään 85 - huonelämpö, minuutin aikana X teholla #if (data['vesi']['varaajan_status'] / data['vesi']['varaajan_kapasiteetti']) * 100 < 30 and GPIO.input(25) == 0: #Jos varaajan status on alle X % JA varaaja ei vielä ole päällä (päiväsaika), pakotetaan se päälle automaattisesti #Tämän ehdon ei pitäisi toteutua yöllä - kärkitila on silloin 1 - varaaja on jo valmiiksi päällä #data['vesi']['varaajan_pakotus'] = True #logi("Varaaja pakotettiin automaattisesti päälle!") varaajan_hoitaja() #tuulettimen_ohjaus() try: with open("demofile3.txt", "w") as f: f.write(json.dumps(data)) f.close() except: logi("HEARTHBEAT EI ONNISTUNUT TALLENNUKSESSA") logi("Hearthbeat - Kutsutaan laskuria: ") odotusaika = 60 - (round(time.time() - offset_aika)) #Vähennetään minuutin odotusajasta näihin kulunut aika if odotusaika < 10: logi("ODOTUSAIKA ALLE 10 SEK") t = threading.Timer(odotusaika, hearthbeat) t.start() def hae_sahkonhinta(paiva = datetime.date.today().strftime('%d-%m-%Y')): global data, sahkonKiinteaOsa data['meta']['nordpoolReqTimes'] += 2 hinnat = [0 for i in range(25)] #Viimeinen indeksi on päivämäärä headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36'} osoite = "http://www.nordpoolgroup.com/api/marketdata/page/10?endDate=" + paiva try: url = requests.get(osoite, headers = headers) except: logi("NORDPOOL ERROR 500") data['meta']['allowNordpoolReq'] = 0 return hinnat vastaus = json.loads(url.text) logi("Nordpool api: " + osoite) for x in range(24): hinta = vastaus["data"]["Rows"][x]["Columns"][5]["Value"] #print(tunti, " ", hinta) if hinnat[x] == ",": hinnat[x] = 0 continue #Lisätään spothintaan alv ja kiinteä pohjahinta eli siirto + marginaali hinnat[x] = ((float(hinta.replace(",", ".")) / 10) * data['elspot_alv']) + sahkonKiinteaOsa[x] #hinnat[x] = (float(hinta.replace(",", ".")) / 10) <--- Tolla saa raakahinnan #hinnat[x] = round((hinnat[x] / 10), 4) hinnat[x] = float(f"{hinnat[x]:.3f}") logi("HAETTIIN HINNAT: " + vastaus["endDate"]) hinnat[24] = vastaus["endDate"].strip() return hinnat def laske_sahkon_kulutus(): global data #teho = round((((1000/(data["sahko"]["pulsseja_per_kwh"] / data["sahko"]["pulssien_otanta"]))*3600)/data["sahko"]["pulssien_vali"])/1000, 3) if time.time() - data['sahko']['lastTimestamp'] < 2: teho = round((((1000/10000)*3600)/data['sahko']['pulssien_vali'])/1000, 3) else: teho = 0 logi("Teho näyttää nollaa") #print(teho) minuutti = int(((datetime.datetime.today()).strftime('%-M'))) tunti = int(((datetime.datetime.today()).strftime('%-H'))) #Tarvitaan edellinen tunti, jotta saadaan kys. tunnin sähkönkulutus kohdistettua oikeaan paikkaan lastHourDateTime = int(((datetime.datetime.today()-datetime.timedelta(hours = 1)).strftime('%-H'))) if data['currentHour'] != tunti: # SUORITETAAN TASATUNNEITTAIN, ja vain kerran data['currentHour'] = tunti spot_hinta_nyt = data['sahko_hinta_tanaan'][tunti] * data['elspot_alv'] #alv prosentteina data['kulutus_spot'] .append(round(data['piirturi_pulssit'] * ( 1 / data['sahko']['pulsseja_per_kwh']), 3)) #Summataan kumulatiivisesti joka tunti kulutus * pörssihinta: data['kumul_spot_kokonaishinta'] += (data['piirturi_pulssit'] * ( 1 / data['sahko']['pulsseja_per_kwh'])) * spot_hinta_nyt #Lisätään tämän tunnin kulutus x elspot hinta kokonaishintaan ####### VARAAJAN OHJAUKSEN MYÖTÄ TEHTYJÄ data['sahko']['hintaTunneittain'][lastHourDateTime] += (data['piirturi_pulssit'] * ( 1 / data['sahko']['pulsseja_per_kwh'])) * data['sahko_hinta_tanaan'][lastHourDateTime] logi("Varaajan kärkitila ennen päälläoloehtoa: " + str(GPIO.input(25))) if tunti in data['varaajan_kayntitunnit']: varaajan_hallinta("varaaja_paalle") logi("VARAAJAN KÄYNNISTYSEHTO TÄYTTYI") data['vesi']['varaajan_pakotus'] = False #Päälle laitettu pakotus poistetaan heti ensimmäisen halvan tunnin koittaessa elif data['vesi']['varaajan_pakotus'] == False: # Jos pakotus ei ole päällä, voidaan sammuttaa kun tunti ei ole riittävän halpa varaajan_hallinta("sammuta_varaaja") logi("VARAAJAN SAMMUTUSEHTO TÄYTTYI") else: logi("Varaajalle ei ollut käyntituntia, mutta pakotus oli True") #Tämän pitäisi toteutua, jos pakotus on päällä logi("Ei tehdä mitään ...") ####### ILP ###### data['ilp']['ilp_count_per_h'].append(data['ilp']['ilp_count']) data['ilp']['ilp_count'] = 0 logi("TUNTI NUMERO: " + str(tunti)) """ # #Varaajan kontaktoria ohjataan avautuvalla koskettimella, varaaja sammuu päivällä vain erikseen käskytettäessä pinout 1:lle #Yötariffi alkaen klo. 22:00 - päättyen 07:00 if tunti < 7 or tunti >= 22: #Operaattorina OR koska tunnit on joko alle TAI yli logi("YÖSÄHKÖN TUNTI") data['vesi']['varaajan_pakotus'] = False #Poistaa päällepakotuksen, varaaja menee päälle muutenkin nyt, pakotus ei ole voimassa seuraavana päivänä GPIO.output(25, 1) #Lähdön tila = 1, varaajan kontaktori sulkeutuu logi("Varaaja = päällä") data['sahko']['pulssit_yo'] += data['piirturi_pulssit'] # Summataaan Yötunnin pulssit yötariffille if (tunti >= 7 and tunti < 22): #Päivätariffin ehto #Operaattorina AND koska muuten ehto toteutuisi myös klo. 22 jälkeisiltä tunneilta logi("PÄIVÄSÄHKÖN TUNTI") data['sahko']['pulssit_paiva'] += data['piirturi_pulssit'] #Summataan Päivätunnin pulssit päivätariffille if data['vesi']['varaajan_pakotus'] == False: #Jos päällepakotus EI ole päällä GPIO.output(25, 0) #Lähdön tila = 0, varaajan sammuu logi("Varaaja = kiinni") else: #Jos halutaan tehdä jotain tässäkohtaa ... logi("Varaaja on pakotettuna päälle päivällä! Ei tehty mitään!") """ ################## logi("TUNTI nro. " + str(tunti) + "vaihtunut!") logi("Varaajan kärkitila sen jälkeen: " + str(GPIO.input(25))) data['piirturi_pulssit'] = 0 #Nollataan pulssilaskuri uutta tuntia varten data['meta']['tuntilaskuri'] += 1 data['sahko']['realTimeMonitorLog'].append(teho) ####### ILPin hetkellinen teho ############# if data['ilp']['ilp_delay'] > 0: data['ilp']['ilp_teho'] = round((((1000/1000)*3600)/data['ilp']['ilp_delay'])/1000, 3) def vesimittari(channel): #Keskeytyshaaskat kutsuu aina tämän paikalle, jos GPIO nastoissa tapahtuu jotain global data #Keskeytyksissä summataan pulssit SEKÄ lasketaan taajuus if channel == 17: data['sahko']['pulssien_vali'] = time.time() - data['sahko']['lastTimestamp'] data['sahko']['kulutusTunneittain'][data['currentHour']] += 1 data['piirturi_pulssit'] += 1 data['sahko']['lastTimestamp'] = time.time() return 0 if channel == 26: data['vesi']['taajuus'] = 1 / (time.time() - data['vesi']['lastTimestamp']) data['vesi']['lastTimestamp'] = time.time() data['vesi']['ulkokierto_count'] += 1 return 0 if channel == 13: data['vesi']['kylma_vesi_taajuus'] = 1 / (time.time() - data['vesi']['kylma_vesi_lastTimestamp']) data['vesi']['kylma_vesi_lastTimestamp'] = time.time() data['vesi']['kylma_vesi_count'] += 1 return 0 if channel == 6: data['ilp']['ilp_delay'] = time.time() - data['ilp']['lastTimestamp'] data['ilp']['ilp_count'] += 1 data['ilp']['lastTimestamp'] = time.time() def pysayta_mittari(): #Kun virtaus pysähtyy, ei keskeytystä enään tule == ei jätetä edellistä taajuuslukemaa päälle global data if time.time() - data['vesi']['lastTimestamp'] > 1: data['vesi']['taajuus'] = 0 if time.time() - data['vesi']['kylma_vesi_lastTimestamp'] > 1: data['vesi']['kylma_vesi_taajuus'] = 0 if time.time() - data['ilp']['lastTimestamp'] > 360: data['ilp']['lastTimestamp'] = time.time() logi("Nollattiin ILPin mittari") data['ilp']['ilp_teho'] = 0 #if time.time() - data['sahko']['lastTimestamp'] > 1: # data['sahko']['pulssien_vali'] = False def mittaa_lampotila(): global f val_2 = ADS.readADC(0) val_1 = ADS.readADC(2) jannite = val_2 * f vastus = round(47000 / ((val_1 * f) / jannite -1), 2) #print("Analog2: {0:d}\t{1:.3f} V".format(val_2, jannite)) #B VALUE = 3950 lampo = (1 / (1 / 298.16 +1 / 3950 * ln(vastus / 50000))) - 273.15 #print(lampo , "vastus: " , vastus, "3.3 jannite: ", val_1 * f) return lampo def logi(txt): print("[", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), " ] ", txt) data['lastLogs'].append("[" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + "] " + txt + "") time.sleep(1) class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): logi("Threaded Mixin luokkaa kutsutaan!") """Handle requests in a separate thread.""" def create_server(): port = 3323 global data, vesi httpd = ThreadedHTTPServer(("0.0.0.0", port), handler) logi("HTTP KUUNTELEE PORTISSA " + str(port)) httpd.serve_forever() try: #Jos data array on aiemmin dumpattu tiedostoon talteen with open("demofile3.txt", "r") as file: logi("TIEDOSTO LÖYTYI") data = json.loads(file.read()) file.close() except: logi("Ei tiedostoa") #ADS = ADS1x15.ADS1115(1, 0x48) #ADS.setGain(ADS.PGA_4_096V) #f = ADS.toVoltage() #ADS.setDataRate(0) #Haaskat odottamassa: benchmark = False if benchmark == False: GPIO.setmode(GPIO.BCM) GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #Kuuma vesi GPIO.add_event_detect(26, GPIO.FALLING, bouncetime=2) GPIO.add_event_callback(26, vesimittari) GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #Kylmä vesi GPIO.add_event_detect(13, GPIO.FALLING, bouncetime=2) GPIO.add_event_callback(13, vesimittari) GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #Sähkömittari GPIO.add_event_detect(17, GPIO.FALLING, bouncetime=2) GPIO.add_event_callback(17, vesimittari) GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # ILP sähkömittari GPIO.add_event_detect(6, GPIO.FALLING, bouncetime=30) GPIO.add_event_callback(6, vesimittari) #GPIO.setup(21, GPIO.OUT, initial=GPIO.LOW) #GPIO.setup(20, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(25, GPIO.OUT, initial=GPIO.HIGH) #Varaajan kärki. Avautuva kosketin = oletuksena varaajan kontaktorille avautuva kosketin, varaaja silloin päällä for i in range(5): time.sleep(1) logi("odotetaan " + str(i)) #Kodin hengetär tekee ns. raskaat, aikaa vievät työt ja paskahommat #Sekunttikierto laskee veden kulutukset ja sen keston täytyy olla tarkasti sekuntti time.sleep(1) _thread.start_new_thread(kodin_hengetar, tuple()) logi("Kodin hengerät käynnistetty!") hearthbeat() logi("hearthbeat() käynnistetty!") time.sleep(1) _thread.start_new_thread(create_server, tuple()) data['meta']['restartTimes'] += 1 kaynnistysaika = math.ceil(time.time()) try: start = time.time() while True: #Mainloop ei tee muuta kuin odottaa pysäytyskäskyä näppikseltä #print(data["vesi"]["ulkokierto_count"]) #print(data["sahko"]["pulssien_vali"]) #time.sleep(1 / 183.333) #vesimittari(26) #print(time.time() - start) time.sleep(2) except KeyboardInterrupt: #logi("tallennetaan data") #file = open("demofile3.txt", "w") #file.write(json.dumps(data)) #file.close() data['meta']['ajoaikaSec'] += (math.ceil(time.time()) - kaynnistysaika) print("\nTidying up")
SELAINPUOLI
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> aside { width: 25%; padding-left: 15px; margin-left: 15px; float: right; background-color: lightgray; } section { margin: 10px; padding: 10px; } </style> <body> <div id="kulutus"></div> <nav style="font-size:1.5vw; background-color: Aquamarine; padding: 5px;" id="tiedot"></nav> <section style="font-size:1.5vw;background-color: rgba(255, 255, 255, 0.1); float: right; " id="kulutusajakauma"></section> <section style="font-size:1.5vw;background-color: rgba(255, 255, 255, 0.4);" id="ilp"></section> <section style="font-size:1.5vw;background-color: rgba(255, 255, 255, 0.4);" id="tuntitieto"></section> <!--<svg id="kulutus_bars" width='400' height='100' style="border: 1px solid black;" ></svg>--> <aside style="font-size:1.5vw;"> <h4>Veden kulutus tänään</h4> <p style=" border: 1px dotted blue; padding: 5px; margin: 5px;"> <span style="color: blue;" id="kylmavesi"></span><br /> <span style="color: red;" id="kuumavesi"></span><br /> <span style="color: green;" id="lammitysteho"></span><br /> <span id="veden_arvo"></span> <span id="ulkokierron_lammot"></span> </p> <h4>Veden kulutus päivittäin</h4> <span id="vesi_paivittain"></span> <p> <!--<span style="color: green;" id="saasto"></span><br /> <span id="paluulampo"></span><br /><br />---> <button onclick="pakota_varaaja_paalle()">Pakota varaaja päälle</button><br /> <span><canvas id="varaajan_tila" width="200" height="30" style="border:1px solid balck; margin: 10px;"></span> <span id="varaajan_lataus"></span> <!-- <span style="color: magenta; text-decoration: underline;">Kuuman veden arvo:</span> --> </p> <p style="border: 1px solid black; margin: 5px; padding: 5px;"> <span style="text-decoration: underline;">Ajonaikaisia tietoja</span><br /><br /> <span>JavaConsole:<br /></span> <textarea rows="1" cols="1" id="javaLog" style="width: 200px; height: 50px;"></textarea><br /> <span id="saikeita"></span><br /> <span id="lahetetty"></span><br /> <span id="pulsseja"></span><br /> <span id="nordpool"></span><br /> <span id="nordpoolaccess"></span> <span id="pvm"></span><br /> <span id="paikalla"></span><br /> <span id="pyyntoja"></span><br /> <span id="restartTimes"></span><br /> <span id="ajoaika"></span><br /> <a href="./debug">DEBUG</a><br /> </p> </aside> <!---<div id="myPlot" style="width:60%; margin-top: 10%px; height: 400px; border: 1px solid black;"></div> <!---<h1>ILP kulutus</h1> <div id="ILP" style="width:100%;max-width:600px; height: 400px; border: 1px solid black;"></div> <!--<h1>Veden kulutus</h1> <div id="vesi" style="width:100%;max-width:600px; height: 400px; border: 1px solid black;"></div>---> <button onclick="nayta_ilp_naytto()">Näytä ILP sähkö</button> <button onclick="nayta_sahkonhinta()">Näytä sähkön hinta</button> <button onclick="nayta_vedenkulutus()">Näytä veden kulutus</button> <button onclick="nayta_kulutusjakauma()">Näytä kulutusjakauma</button> <button onclick="varaajan_suunnitelma()">Varaajan suunnitelma</button> <div style="width: 600px; border: 1px solid black;margin: 5px;"><canvas id="myChart"></canvas></div> <button onclick="nayta_kaikkilammot()">Kaikki lämmöt</button> <button onclick="nayta_lammot_tunti()">Viimeisin tunti</button> <div style="width: 600px; border: 1px solid black; margin: 5px;"><canvas id="lammot"></canvas></div> <h3 style="">Logi</h3> <textarea rows="10" cols="10" id="lastlog" style="width: 60%; height: 100px;"></textarea> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> </body> </html> <script> /*window.addEventListener('load', () => { document.body.style.backgroundColor = 'yellow'; });*/ var ylempiGraafi = "sahkon_hinta"; var lampoGraafi = "viimeisin_tunti"; function pakota_varaaja_paalle() { fetch("/pakota_varaaja_paalle"); } function nayta_ilp_naytto() { ylempiGraafi = "ilp_kulutus"; hae_kaikki_data(); //fetch("/etusivu.html"); } function nayta_sahkonhinta() { ylempiGraafi = "sahkon_hinta"; hae_kaikki_data(); //fetch("/etusivu.html"); } function nayta_vedenkulutus() { ylempiGraafi = "veden_kulutus"; hae_kaikki_data(); } function nayta_kulutusjakauma() { ylempiGraafi = "kulutusjakauma"; hae_kaikki_data(); } function varaajan_suunnitelma() { ylempiGraafi = "varaajan_suunnitelma"; hae_kaikki_data(); } function nayta_kaikkilammot() { lampoGraafi = "kaikki"; hae_kaikki_data(); } function nayta_lammot_tunti() { lampoGraafi = "viimeisin_tunti"; hae_kaikki_data(); } function varaaja_canvas(lataus) { // console.log("Varaajan lataus:" + lataus); var c = document.getElementById("varaajan_tila"); var ctx = c.getContext("2d"); var grd = ctx.createLinearGradient(0, 0, 200, 0); grd.addColorStop(0, "blue"); grd.addColorStop(1, "red"); // Fill with gradient ctx.fillStyle = grd; ctx.fillRect(0, 0, 200 * lataus, 20); } function viivasto_y (tiheys, max_y, max_x, style = "stroke:black;stroke-width:1 px") { let output = "", i, y_pointer = 0 / tiheys, x_offset = 0, x = 0 ; for (i = 0; i < tiheys; i++) { output += `<line x1="${x_offset}" y1="${y_pointer + (max_y / tiheys)}" x2="${max_x}" y2="${y_pointer + (max_y / tiheys)}" style="${style}" />` + "\n"; y_pointer += max_y / tiheys; } //console.log(output); return output; } function viivasto_y (tiheys, max_x, max_y, style = "stroke:black;stroke-width:1 px") { let output = "", i, y_pointer = 0 / tiheys, x_offset = 0, x = 0 ; for (i = 0; i < tiheys; i++) { output += `<line x1="${x_offset}" y1="${y_pointer + (max_y / tiheys)}" x2="${max_x}" y2="${y_pointer + (max_y / tiheys)}" style="${style}" />` + "\n"; y_pointer += max_y / tiheys; } //console.log(output); return output; } function arvo_luvut(montako) { const a = []; for (let i = 0; i < montako; i++) { a[i] = Math.floor(Math.random() * 100); //console.log(Math.floor(Math.random() * 100)); } console.log(a); return a; } function generate_points(values, max_y = 600, max_x = 600) { //let values = [20,20,50,30,30,20]; let minmax = get_minMax(values); let output = "", i, x_step = Math.trunc(max_x / values.length), y_step = max_y / minmax[1], x_pointer = 0, y_ax = 0; //console.log("x-step values : " + values + max_y, max_x); //console.log("pituus: " + values.length); //console.log(get_minMax(values)); for (i = 0; i < values.length; i++) { //console.log(values[i]); y_ax = max_y - Math.trunc(values[i] * y_step); output += x_pointer + "," + y_ax + " "; x_pointer += x_step; //console.log("x-step : " + x_step); //console.log("x-pointer : " + x_pointer); //console.log("y-ax : " + y_ax); //console.log("output : " + output); } output = output.substr(0, output.length); //console.log("generate points : " + output); return output; } function sum_element(a) { let s = 0; for (i = 0; i < a.length; i++) { s += a[i]; } return s; } function generate_bars (values, x_max, y_max, style = `style="fill:green;fill-opacity:0.4;stroke:green;stroke-width:1"`, x_margin, y_margin) { let output = "", i, x_pointer = x_margin, x_step = 0, y_fact, vaihtelu = 0; let minmax = get_minMax(values); x_step = (x_max / values.length) - 3 ; y_fact = ( (y_max - y_margin) / minmax[1]); y_line = ( y_max * 0.4) ; output += `<line x1="0" y1="${y_line}" x2="${x_max}" y2="${y_line}" style="stroke:black" />\n`; for (i = 1; i < values.length; i++) { output += `<rect width="${x_step }" height="${ ((values[i]) * (y_fact))}" x="${x_pointer}", y="${y_max - (values[i] * y_fact)}" ${style} />` + "\n"; x_pointer = x_pointer + x_step + 3; } return output; } function precise(x, m = 3) { return x.toPrecision(m); } function get_minMax(arr) { const min = Math.min(...arr); const max = Math.max(...arr); const index_min = arr.indexOf(min); const index_max = arr.indexOf(max); return [arr[index_min], arr[index_max], (arr[index_max] - arr[index_min]) ]; } function ulosta(id, txt) { document.getElementById(id).innerHTML = txt; } function ulostaJava(asia) { javaLog.unshift(asia); console.log(asia); } let sahkovero = 0.0279372; let energiahinta = 0.221; var source = new EventSource("/nayttopaate66/livestream"); const realTimeMonitorLog = []; const lastlogLammot = {'imu': [], 'puhallus': [], 'ottoteho': [], 'ottoteho_avg': [], 'lammitysteho' : []}; const lastLog = []; const hinnat = {'paiva' : {'energia' : 0.2210, 'siirto' : 0.0408}, 'yo' : {'energia' : 0.1490, 'siirto' : 0.0267}, 'sahkovero' : 0.0279372, 'yksAikaHinta' : 0.1990}; const d = new Date(); const javaLog = []; var laskuri = 0; var kokonaishinta_paiva = hinnat['paiva']['siirto'] + hinnat['paiva']['energia'] + hinnat['sahkovero']; var kokonaishinta_yo = hinnat['yo']['siirto'] + hinnat['yo']['energia'] + hinnat['sahkovero']; var kokonaishinta_yksAika = hinnat['paiva']['siirto'] + hinnat['yksAikaHinta'] + hinnat['sahkovero']; var energian_hinta_nyt, paivaVaiYo, paivaVaiYo_color; source.onmessage = function(event) { const obj = JSON.parse(event.data); //console.log(obj['lastLogs']); let output; realTimeMonitorLog.push((obj['realTimeMonitorLog'])); lastlogLammot['imu'].push(obj['parvi']); lastlogLammot['puhallus'].push(obj['sisa_puhallus']); lastlogLammot['ottoteho'].push(obj['ilp_teho'] * 1000); //lastlogLammot['lammitysteho'].push((((obj['sisa_puhallus'] - obj['parvi']) * 800 * 1.25) / 3600).toFixed(2)); ulosta('tuntitieto', "Sähkön hinta nyt: " + obj['sahkon_hinta_nyt'].toFixed(2) + " c Meneillään oleva tunti: " + obj['kuluva_tunti']); laskuri++; //ulostaJava(laskuri); if (laskuri == 60) { lastlogLammot['ottoteho_avg'].push(lastlogLammot['ottoteho'].reduce((a,c) => a + c, 0) / lastlogLammot['ottoteho'].length); laskuri = 0; } let COP = ((((obj['sisa_puhallus'] - obj['parvi']) * 800 * 1.25) / 3600).toFixed(2) / ((lastlogLammot['ottoteho'].reduce((a,c) => a + c, 0) / lastlogLammot['ottoteho'].length) / 1000)).toFixed(2); //console.log(lastlogLammot); if (d.getHours() < 7 || d.getHours() >= 22) { energian_hinta_nyt = kokonaishinta_yo; paivaVaiYo = "yötunnilta"; paivaVaiYo_color = 'blue'; } if (d.getHours() >= 7 && d.getHours() < 22) { energian_hinta_nyt = kokonaishinta_paiva; paivaVaiYo = "päivätunnilta"; paivaVaiYo_color = 'OrangeRed'; } //const numbers = [3,4,5,2,4,6,78,53,2,1,2]; //const sum = numbers.reduce((a,c) => a + c, 0); //const avg = sum / numbers.length; if (lastlogLammot['imu'].length > 300) { lastlogLammot['imu'].shift(); } if (lastlogLammot['puhallus'].length > 300) { lastlogLammot['puhallus'].shift(); } if (lastlogLammot['ottoteho'].length > 60) { lastlogLammot['ottoteho'].shift(); } if (lastlogLammot['ottoteho_avg'].length > 10) { lastlogLammot['ottoteho_avg'].shift(); } if (lastlogLammot['lammitysteho'].length > 60) { lastlogLammot['lammitysteho'].shift(); } if (realTimeMonitorLog.length > 100) { realTimeMonitorLog.shift(); } if (obj['lastLogs'] != 0) { lastLog.unshift(obj['lastLogs']); } if (lastLog.length > 7000) { lastLog.pop(); } const p = new Date(); ulostaJava(((p.getMinutes() + p.getSeconds() / 60) / 60)) let kuluvaTunti = d.getHours(); let teho_keskimaarin = ((obj['pulsseja_laskettu'] * 0.0001) / (obj['meta']['tuntilaskuri'] + (p.getMinutes() / 60))).toFixed(3); // huomioidaan kuluvan tunnin minuutit mukaan keskiarvon pituuteen //teho_keskimaarin = teho_keskimaarin * 2; let vari, r = 0, g = 0, b = 0, t = 0.5; if (obj['realTimeMonitorLog'] < teho_keskimaarin) { t = precise(1 - (obj['realTimeMonitorLog'] / teho_keskimaarin), 2); g = 255; } if (obj['realTimeMonitorLog'] >= teho_keskimaarin) { t = precise(1 - (teho_keskimaarin / obj['realTimeMonitorLog']), 2); r = 255; } if (t > 1) { t = 1; } if (t <= 0) { t = 0.02; } vari = `rgba(${r}, ${g}, ${b}, ${t})`; console.log(obj['sahkon_hinta_nyt']); ulosta("kulutus", "<header style='font-size:5vw; text-align: center; background-color: " + vari + ";'>" + obj['realTimeMonitorLog'].toFixed(2) + " kW, " + "" + (obj['realTimeMonitorLog'] * (obj['sahkon_hinta_nyt']) / 100).toFixed(2) + "" + " eur/h, == " + ((obj['realTimeMonitorLog'] * (obj['sahkon_hinta_nyt']) / 100) * 24).toFixed(2) + " eur/päivä </header>"); ulosta("tiedot", "" + "Kumulatiivinen: <b>" + (obj['pulsseja_laskettu'] * 0.0001).toFixed(3) + "</b> kWh, <s>euroja kulunut " + (obj['pulsseja_laskettu'] * 0.0001 * energiahinta).toFixed(2) + " euroa.</s> (Energian osuus: <b>" + (obj['kumul_spot_kokonaishinta'] / 100).toFixed(2) + "</b> eur spot, Yleissähkömittauksella: <b>" + ((obj['pulsseja_laskettu'] * 0.0001) * hinnat['yksAikaHinta']).toFixed(2) + "</b> EUR)<br />" + "Liittymäteho keskimäärin: " + teho_keskimaarin + " kW"); ulosta('kulutusajakauma', "<s><span style='color: OrangeRed;'>Päivätunnit: <b>" + (obj['pulssit_paiva'] / 10000).toFixed(1) + "</b> kWh, <b>" + ((obj['pulssit_paiva'] / 10000) * kokonaishinta_paiva).toFixed(2) + "</b> EUR</span>, <span style='color: blue;'>Yötunnit: <b>" + (obj['pulssit_yo'] / 10000).toFixed(1) + "</b> kWh, <b>" + ((obj['pulssit_yo'] / 10000) * kokonaishinta_yo).toFixed(2) + "</b> EUR, </span><span style='color: magenta;'>== <b>" + ((obj['pulssit_paiva'] / 10000) + (obj['pulssit_yo'] / 10000)).toFixed(1) + "</b> kWh (<b>" + (((obj['pulssit_paiva'] / 10000) * kokonaishinta_paiva) + ((obj['pulssit_yo'] / 10000) * kokonaishinta_yo)).toFixed(2) + "</b> EUR </span>" + ",<br /><span style='color: " + paivaVaiYo_color + "'>Kuluvalta " + paivaVaiYo + ": <b>" + (obj['piirturi_pulssit'] / 10000).toFixed(4) + "</b> kWh, <b>" + ((obj['piirturi_pulssit'] / 10000) * energian_hinta_nyt).toFixed(2) + "</b> EUR</span>, Kokonaishinta 1-aikamittauksella: <b>" + ((obj['pulsseja_laskettu'] / 10000) * (kokonaishinta_yksAika)).toFixed(2) + "</b> EUR</s>"); // Puhallusteho m3/h 800/720/570/620/560/500/450 let antoteho = ((((obj['sisa_puhallus'] - obj['parvi']) * 800 * 1.25) / 3600).toFixed(2)); if (antoteho < 0) { antoteho = "<span style='color: blue;'>Jäähdytysteho: <b>" + (antoteho * -1) + "</b> kW</span>"; } else { antoteho = "<span style='color: red;'>Lämmitysteho: <b>" + antoteho + "</b> kW</span>"; } ulosta('ilp', "ILP kokonaiskulutus: <b>" + (obj['ilp_count'] / 1000).toFixed(3) + "</b> kWh<br /> " + "Ottoteho: <b>" + (obj['ilp_teho'] * 1000).toFixed(1) + "</b>" + " W / <b>" + (lastlogLammot['ottoteho'].reduce((a,c) => a + c, 0) / lastlogLammot['ottoteho'].length).toFixed(1) +"</b> W/avg, <br />" + antoteho + ",<br /> COP: " + COP + " ,<br />Ottoteho / 10min:" + lastlogLammot['ottoteho_avg'].reduce((a,c) => a + c, 0) / lastlogLammot['ottoteho_avg'].length.toFixed(2) + "<br />Ulkolämpö: <b>" + obj['ulkolampo'].toFixed(2) + "</b> c, sisälämpö: <b>" + obj['sisalampo'].toFixed(2) + "</b> c, lämpö parvella: <b>" + obj['parvi'].toFixed(2) + "</b> c ; Puhalluslämpö: <b>" + obj['sisa_puhallus'].toFixed(2) + "</b> c <br />" + ""); // Vesimittarien kertoimet 1/2 = 11 ja 3/4 = 6.6 document.getElementById("saikeita").innerHTML = "Säikeitä käynnissä: " + obj['meta']['saikeitaKaynnissa']; //document.getElementById("lahetetty").innerHTML = "Dataa lähetetty: " + obj['meta']['broadcastedBytes']; ulosta("lahetetty", "Dataa lähetetty: " + ((obj['meta']['broadcastedBytes'] / 1024 / 1024).toFixed(3)) + " MB"); document.getElementById("pvm").innerHTML = "Päivämäärä: " + obj['meta']['paivamaaraTanaan']; document.getElementById("nordpool").innerHTML = "NordPooliin pyynnöt: " + obj['meta']['nordpoolReqTimes']; document.getElementById("pulsseja").innerHTML = "Pulsseja laskettu: " + obj['pulsseja_laskettu']; document.getElementById("lastlog").innerHTML = "" + lastLog.join("\n"); document.getElementById("paikalla").innerHTML = "Asiakkaita paikalla: " + obj['meta']['asiakkaitaPaikalla']; document.getElementById("pyyntoja").innerHTML = "HTTP pyyntöjä saatu: " + obj['meta']['httpPyyntojaSaatu']; document.getElementById("restartTimes").innerHTML = "Datadumppi käynnistetty: " + obj['meta']['restartTimes'] + " kertaa"; ulosta("ajoaika", "Uptime käynnistyksestä: <b>" + (obj['meta']['tuntilaskuri'] - obj['meta']['ajoaikaSec'] / 3600) + "</b> h <br /> Ajettu kaikkiaan: <b>" + obj['meta']['tuntilaskuri'] + "</b> h <br /> Datadumppi luotu: " + obj['meta']['datadumppiLuotu'] + ""); document.getElementById("kylmavesi").innerHTML = "Kylmä vesi: <b>" + precise(obj['vesi']['kylma_vesi_count'] / 6.6 / 60, 5) + "</b> l (<b>" + precise(obj['vesi']['kylma_vesi_taajuus']/6.6) + "</b> l/min)"; let kuumanVirtausnopeus = precise(obj['vesi']['taajuus'] / 11); document.getElementById("kuumavesi").innerHTML = "Kuuma vesi: <b>" + precise(obj['vesi']['ulkokierto_count'] / 11 / 60, 5) + "</b> l (<b>" + kuumanVirtausnopeus + "</b> l/min, <b>" + precise(((obj['vesi']['taajuus'] / 11) / 60) * (80 * 4.2)) + "</b> kW )"; //Hetkellinen teho lämpötilaerolla 80 astetta, X virtauksella document.getElementById("lammitysteho").innerHTML = "Ulkokierron lämmitysteho:: <b style='color: red;'>" + precise(((obj['vesi']['taajuus'] / 11) / 60) * ((obj['vesi_ulkokierto_tmp'] - obj['vesi_ulkokierto_meno']) * 4.2)) + "</b> kW"; ulosta("ulkokierron_lammot", "Pöntön lämpötila: <b>" + obj['vesi_ponton_tmp'] + "</b> c, <br /> Kylmän veden menolämpö: <b>" + obj['vesi_ulkokierto_meno'] + "</b> c <br />Ulkokierron paluulämpö: <b>" + obj['vesi_ulkokierto_tmp'] + "</b> c"); //document.getElementById("saasto").innerHTML = "Ulkokierron säästö: " + precise(obj['vesi']['kierron_saasto'], 4) + " kWh (" + precise(obj['vesi']['kierron_saasto'] * (0.0279372 + 0.0408 + 0.089), 2) + " eur)"; //document.getElementById("paluulampo").innerHTML = "Ulkokierron paluulämpö " + precise(obj['vesi']['kierron_paluulampo']) + " c"; //document.getElementById("kuuman_veden_laskelma").innerHTML = "" + ((((obj['vesi']['ulkokierto_count'] / 11 / 60) * 80 * 4.2) * (0.0279372 + 0.0408 + energiahinta)) / 3600).toFixed(2) + " EUR, " + ((obj['vesi']['ulkokierto_count'] / 11 / 60) * 80 * 4.2).toFixed(2) + " kWh"; document.getElementById("varaajan_lataus").innerHTML = "Varaajan latausaste: " + precise(obj['vesi']['varaajan_status'] / obj['vesi']['varaajan_kapasiteetti'] * 100, 4) + " %" + "<br />Veden riittävyys: <span style='font-size: 12px;'>Ohjauskärjen tila: <b>" + obj['varaajan_karkitieto'] + "</b> (0 = kiinni, 1 = päällä)<br />Pakotuksen tila: <b>" + obj['vesi']['varaajan_pakotus'] + "</b></span>"; //let kylman_veden_maara = obj['vesi']['kylma_vesi_count'] / 6.6 / 60; //document.getElementById("veden_arvo").innerHTML = "<br /> <b>" + precise(kylman_veden_maara / 1000 * 2.58) + "</b> EUR (<b>" + precise(kylman_veden_maara / 1000 * (2.58 + 3.19)) + "</b> EUR jätevesineen)<br />Porakaivosta kuoletettu <b>" + precise(kylman_veden_maara / 1000 * (2.58 / 4860 * 100)) + "</b> % <br /> <b>" + precise((4860 / 2.58) - (kylman_veden_maara / 1000), 7) + "</b> kuutiota kuoletukseen " ; ulosta("javaLog", javaLog.join("\n")); } var kk; //vedenkulutusnäyttö var lampoGraafi; var kk_lampo; function sahkon_hinta(txt) { var hinta_tanaan = ((txt['sahko_hinta_tanaan'].map(Number)).slice(0, -1)); var hinta_huomenna = (txt['sahko_hinta_huomenna'].map(Number)).slice(0, -1); console.log(hinta_tanaan); var kylma_paivittain = (txt['vesi_logi']['kylma_paivittain']); var lammin_paivittain = (txt['vesi_logi']['lammin_paivittain']); //console.log(lammin_paivittain); let output = ""; let kuuma_vesi_yhteensa = txt['vesi_logi']['lammin_paivittain'].reduce((x, y)=> x+y); //summaa taulukon output += "<span style='color: blue;'>Kylmä vesi yhteensä: " + ((txt['vesi_logi']['kylma_paivittain'].reduce((x, y)=> x+y))/1000).toFixed(2) + " m3 </span><br />"; output += "<span style='color: red;'>Kuuma vesi yhteensä: " + (kuuma_vesi_yhteensa / 1000).toFixed(2) + " m3,<br />Veden arvo: " + ((80*kuuma_vesi_yhteensa*4.2)/3600) * (kokonaishinta_yo) + " </span><br />"; /*for (i = 0; i < kylma_paivittain.length; i++) { output += "<span style='color: blue;'>" + (kylma_paivittain[i]).toFixed(1) + "</span> \n"; output += "<span style='color: red;'>" + (lammin_paivittain[i]).toFixed(1) + "</span><br />\n"; output += "<hr />\n"; }*/ //console.log(output); document.getElementById("vesi_paivittain").innerHTML = output; //console.log(hinta_huomenna); const xArray = []; xArray.fill("0", 0, 24); //if (hinta_huomenna[0] != 0) { // hinta_tanaan = hinta_tanaan.concat(hinta_huomenna); // xArray.concat(xArray); // } //console.log(hinta_tanaan); var data = [{ x:xArray, y:hinta_tanaan.map(n => (n * 1.09091).toFixed(3)), type:"bar", name: "Hinta tänään" }]; let kiintea_hinta = Array(24); kiintea_hinta.fill(14.9, 0, 7); kiintea_hinta.fill(22.1, 7, 22); kiintea_hinta.fill(14.9, 22, 24); let timestamp = (txt['sahko']['aloitusaika'] * 1000); var luku = (d - timestamp) / 3600000 | 0; //console.log(luku); data.push({x0: ((0 - txt['kulutus_spot'].length) + (d.getHours() + 1)), dx: 1, y: txt['kulutus_spot'], type: "line", yaxis: {range: [0,4]}, name:"Kulutus / kWh"}); data.push({x0: ((0 - txt['kulutus_spot'].length) + (d.getHours() + 1)), dx: 1, y: txt['kulutus_spot'].map(x => x * 21), type: "bar", yaxis: {range: [0,4]}, name:"Hinta / snt"}); //Plotly.newPlot("myPlot", data, layout, {displayModeBar: false, responsive: true}); //console.log(txt['vesi']['varaajan_status']); varaaja_canvas(txt['vesi']['varaajan_status'] / txt['vesi']['varaajan_kapasiteetti']); const dataset=[]; const ctx = document.getElementById('myChart'); if (ylempiGraafi == "varaajan_suunnitelma") { //dataset.push({label: 'Hinta tänään', data: hinta_tanaan.map(n => (n * 1.09091).toFixed(3)), borderWidth: 1, backgroundColor: "#33AEEF"}); suunnitelmat = Array(24+24).fill(0); let lammitysteho = txt['vesi']['varaajan_lammitysteho']; for (i = 0; i < txt['varaajan_kayntitunnit'].length; i++) { suunnitelmat[txt['varaajan_kayntitunnit'][i]] = lammitysteho; //console.log("varaajna käyntitunnit: " + txt['varaajan_kayntitunnit'][i]); } console.log(suunnitelmat); tarve = Array(24+24); tarve.fill(txt['sahko']['varaajan_tarve'] ); let kohtaanto; for (i = 0; i < tarve.length; i++) { //tarve[i] -= suunnitelmat[i]; kohtaanto = tarve[i] - suunnitelmat[i]; if (kohtaanto < 0) { kohtaanto = 0; } tarve.fill(kohtaanto, i, tarve.length); // console.log(tarve[i] + " " + suunnitelmat[i]); } if (hinta_huomenna[0] != 0) { hinta_tanaan.push.apply(hinta_tanaan, hinta_huomenna); } //let aloitus = d.getHours(); let aloitus = 0; console.log(tarve); dataset.push({label: 'Energian suhteellinen hinta', data: hinta_tanaan.map(i => i ).slice(aloitus), borderWidth: 2, pointRadius: 2, fill: false, backgroundColor: "green", borderWidth: 1, borderColor: "green", type: "line"}); dataset.push({label: 'Lämmitystarve / kWh', data: tarve.slice(aloitus), pointRadius: 0, type: 'line', fill: true, borderColor: 'purple', borderWidth: 0, backgroundColor: "rgba(255,10,13,0.1)"}); dataset.push({label: 'Suunniteltu lämmitysajankohta', data: suunnitelmat.slice(aloitus), pointRadius: 0, type: 'bar', fill: false, borderColor: 'purple', borderWidth: 1, backgroundColor: "red"}); if (kk) { kk.destroy(); ulostaJava("TUHOTTIIN VANHA paikassa varaajan suunnitelma"); } let label; label = Array.from({length: 24}, (v, k) => k++ + ":00").slice(aloitus).concat(Array.from({length: 24}, (v, k) => k++ + ":00")); ulostaJava(label); kk = new Chart(ctx, { type: 'bar', data: { //labels: Utils.months({count: 24}), labels: label, datasets: dataset }, options: { title: { display: true, text: 'Kellon aika', position: 'bottom' }, scales: { y: { suggestedMin: 0, suggestedMax: 25 //stacked: 'single' } }, animation: false } }); } if (ylempiGraafi == "sahkon_hinta") { //dataset.push({label: 'Hinta tänään', data: hinta_tanaan.map(n => (n * 1.09091).toFixed(3)), borderWidth: 1, backgroundColor: "#33AEEF"}); dataset.push({label: 'Hinta tänään', data: hinta_tanaan, borderWidth: 1, backgroundColor: "#33AEEF"}); if (hinta_huomenna[0] != 0) { //dataset.push({label: 'Hinta huomenna', data: hinta_huomenna.map(n => (n * 1.09091).toFixed(3)), borderWidth: 1, backgroundColor: "green"}); dataset.push({label: 'Hinta huomenna', data: hinta_huomenna, borderWidth: 1, backgroundColor: "green"}); } dataset.push({label: 'Kiinteä hinta', data: kiintea_hinta, pointRadius: 0, type: 'line', fill: false, borderColor: 'red', borderWidth: 1, backgroundColor: "#33AEEF"}); if (kk) { kk.destroy(); ulostaJava("TUHOTTIIN VANHA paikassa sähköninta"); } kk = new Chart(ctx, { type: 'bar', data: { //labels: Utils.months({count: 24}), labels: Array.from({length: 24}, (v, k) => k++ + ":00"), datasets: dataset }, options: { title: { display: true, text: 'Kellon aika', position: 'bottom' }, animation: false } }); console.log(kk); } let osoitin = Array(24); osoitin[10] = 100; if (ylempiGraafi == "kulutusjakauma") { dataset.push({label: 'Kulutus kWh', data: txt['sahko']['kulutusTunneittain'].map(i => (i / 10000).toFixed(3)), borderWidth: 1, backgroundColor: "#33AEEF"}); dataset.push({label: 'Hinta tunneittain', data: txt['sahko']['hintaTunneittain'].map(i => (i / 100).toFixed(2)), borderWidth: 1, backgroundColor: "red"}); if (txt['meta']['tuntilaskuri'] > 24) { dataset.push({label: 'Teho keskimäärin', data: txt['sahko']['kulutusTunneittain'].map(i => (i / 10000) / (txt['meta']['tuntilaskuri'] / 24).toFixed(2)), borderWidth: 1, backgroundColor: "red", type: "line"}); } if (kk) { kk.destroy(); ulostaJava("TUHOTTIIN VANHA paikassa kulutusjakauma"); } kk = new Chart(ctx, { type: 'bar', data: { //labels: Utils.months({count: 24}), labels: Array.from({length: 24}, (v, k) => k++ + ":00"), datasets: dataset }, options: { title: { display: true, text: 'Kellon aika', position: 'bottom' }, animation: false } }); console.log(kk); } if (ylempiGraafi == "ilp_kulutus") { //const teho_keskimaarin = []; //teho_keskimaarin.fill(txt['ilp']['ilp_count_per_h'].reduce((a, b) => (a + b / 1000), 0) / txt['ilp']['ilp_count_per_h'].length); dataset.push({label: 'Kulutus / kWh', data: txt['ilp']['ilp_count_per_h'].map(i => i / 1000), borderWidth: 1, pointRadius: 0, backgroundColor: "#33AEEF"}); dataset.push({label: 'Ottoteho keskimäärin', data: Array(txt['ilp']['ilp_count_per_h'].length).fill(txt['ilp']['ilp_count_per_h'].reduce((a, b) => (a + b / 1000), 0) / txt['ilp']['ilp_count_per_h'].length), borderWidth: 1, pointRadius: 0, backgroundColor: "green", fill: true}); //ulostaJava(teho_keskimaarin); //dataset.push({label: 'Teho keskimäärin', data: teho_keskimaarin, pointRadius: 0, type: 'line', fill: false, borderColor: 'red', borderWidth: 1, backgroundColor: "#33AEEF"}); if (kk) { kk.destroy(); ulostaJava("TUHOTTIIN VANHA paikassa ilp kulutus"); } kk = new Chart(ctx, { type: 'line', data: { labels: Array.from({length: txt['ilp']['ilp_count_per_h'].length}, (v, k) => k++), datasets: dataset }, options: { animation: false } }); } if (ylempiGraafi == "veden_kulutus") { // Tapahtuu napista veden kulutus ulostaJava("veden kulutus"); ////Lisätään näytettäviin kulutuksiin myös reaaliaikainen tieto mittariltä, kuluvalta päivältä txt['vesi_logi']['kylma_paivittain'].shift(); //Alussa tulee aina tyhjä jostain syystä, tässä ppoistetaan se txt['vesi_logi']['kylma_paivittain'].push(txt['vesi']['kylma_vesi_count'] / 6.6 / 60); txt['vesi_logi']['lammin_paivittain'].shift(); txt['vesi_logi']['lammin_paivittain'].push(txt['vesi']['ulkokierto_count'] / 11 / 60); let vesi_x_label = Array.from({length: txt['vesi_logi']['kylma_paivittain'].length - 1}, (v, k) => k + 1); vesi_x_label.push("Tänään"); //let vesi_yhteensa = txt['vesi_logi']['kylma_paivittain'].map((a, i) => a + txt['vesi_logi']['lammin_paivittain'][i]); //console.log(vesi_yhteensa); //////// dataset.push({label: 'Kylmä vesi', data: txt['vesi_logi']['kylma_paivittain'].map(i => i.toFixed(0)), borderWidth: 1, pointRadius: 0, backgroundColor: "blue", stack: 'Stack 0'}); dataset.push({label: 'Kuuma vesi', data: txt['vesi_logi']['lammin_paivittain'].map(i => i.toFixed(0)), borderWidth: 1, pointRadius: 0, backgroundColor: "red", stack: 'Stack 0'}); //dataset.push({label: 'Yhteensä', data: vesi_yhteensa.map(i => i.toFixed(0)), borderWidth: 1, pointRadius: 0, backgroundColor: "yellow", stack: 'Stack 0'}); if (kk) { //tuhotaan aiempi canvas ainoastaa, jos sellainen on aiemmin luotu kk.destroy(); ulostaJava("TUHOTTIIN VANHA paikassa veden kulutus"); } kk = new Chart(ctx, { type: 'bar', data: { //labels: Array.from({length: txt['vesi_logi']['kylma_paivittain'].length}, (v, k) => k + 1), labels: vesi_x_label, datasets: dataset }, options: { scales: { x: { stacked: true, title: { color: 'green', display: true, text: 'Päivä' } }, y: {stacked: true} }, animation: false } }); } //txt['vesi_logi']['kylma_paivittain'].map(i => i.toFixed(0)) txt['ilp']['sisalampo'].shift(); txt['ilp']['ulkolampo'].shift(); txt['ilp']['sisa_puhallus'].shift(); txt['ilp']['parvi'].shift(); for (i = 0; i < txt['ilp']['ilp_ottoteho_log'].length; i++) { if (txt['ilp']['ilp_ottoteho_log'][i] > 3) { txt['ilp']['ilp_ottoteho_log'][i] = txt['ilp']['ilp_ottoteho_log'][i - 1]; ulostaJava(txt['ilp']['ilp_ottoteho_log'][i]); } } if (kk_lampo) { kk_lampo.destroy(); } const dataset_lammot = []; var labels_lammot = []; const ctx_h = document.getElementById('lammot'); if (lampoGraafi == "kaikki") { dataset_lammot.push({label: 'Huonelämpö', data: txt['ilp']['sisalampo'], borderWidth: 1, pointRadius: 0, borderColor: "green", fill: false}); dataset_lammot.push({label: 'Imulämpö parvella', data: txt['ilp']['parvi'], borderWidth: 1, pointRadius: 0, borderColor: "magenta", fill: false}); dataset_lammot.push({label: 'Puhalluslämpö parvella', data: txt['ilp']['sisa_puhallus'], borderWidth: 1, pointRadius: 0, borderColor: "red", fill: false}); dataset_lammot.push({label: 'Ulkolämpö', tension: 0, data: txt['ilp']['ulkolampo'], borderWidth: 1, pointRadius: 1, borderColor: "blue", fill: false}); dataset_lammot.push({label: 'Ottoteho awg/min', type: 'bar', tension: 0, data: txt['ilp']['ilp_ottoteho_log'].map(i => i * 10), borderWidth: 1, pointRadius: 0, borderColor: "brown", fill: false}); dataset_lammot.push({label: 'Ulkokierron paluu', data: txt['vesi_logi']['kierron_paluulampo'], borderWidth: 1, pointRadius: 0, borderColor: "magenta", fill: false}); dataset_lammot.push({label: 'Pöntön lämpötila', data: txt['vesi_logi']['ponton_lampotila'], borderWidth: 1, pointRadius: 0, borderColor: "magenta", fill: false}); dataset_lammot.push({label: 'Raakaveden lämpötila', data: txt['vesi_logi']['kierron_menolampo'], borderWidth: 1, pointRadius: 0, borderColor: "green", fill: false}); labels_lammot = (Array.from({length: txt['ilp']['sisalampo'].length}, (v, k) => k++)); } if (lampoGraafi == "viimeisin_tunti") { dataset_lammot.push({label: 'Huonelämpö', data: txt['ilp']['sisalampo'].slice(-60), borderWidth: 1, pointRadius: 0, borderColor: "green", fill: false}); dataset_lammot.push({label: 'Imulämpö parvella', data: txt['ilp']['parvi'].slice(-60), borderWidth: 1, pointRadius: 0, borderColor: "magenta", fill: false}); dataset_lammot.push({label: 'Puhalluslämpö parvella', data: txt['ilp']['sisa_puhallus'].slice(-60), borderWidth: 1, pointRadius: 0, borderColor: "red", fill: false}); dataset_lammot.push({label: 'Ulkolämpö', tension: 0, data: txt['ilp']['ulkolampo'].slice(-60), borderWidth: 1, pointRadius: 1, borderColor: "blue", fill: false}); dataset_lammot.push({label: 'Ottoteho awg/min', type: 'bar', tension: 0, data: txt['ilp']['ilp_ottoteho_log'].map(i => i * 1).slice(-60), borderWidth: 1, pointRadius: 0, borderColor: "brown", fill: false}); dataset_lammot.push({label: 'Ulkokierron paluu', data: txt['vesi_logi']['kierron_paluulampo'].slice(-60), borderWidth: 1, pointRadius: 0, borderColor: "magenta", fill: false}); dataset_lammot.push({label: 'Pöntön lämpötila', data: txt['vesi_logi']['ponton_lampotila'], borderWidth: 1, pointRadius: 0, borderColor: "magenta", fill: false}); dataset_lammot.push({label: 'Raakaveden lämpötila', data: txt['vesi_logi']['kierron_menolampo'], borderWidth: 1, pointRadius: 0, borderColor: "green", fill: false}); labels_lammot = (Array.from({length: 60}, (v, k) => k++)); } kk_lampo = new Chart(ctx_h, { type: 'line', data: { labels: labels_lammot, //labels: Array.from({length: txt['ilp']['sisalampo'].length}, (v, k) => k++), datasets: dataset_lammot, options: { scales: { x: { type: 'linear', grace: '5%' } } } } }); /* var ilpLayout = { title: "ILP kulutus", xaxis: { title: "Aika" }, yaxis: { title: "Kulutus per h", } } var ilp_kulutus_tunneittain; console.log(txt['ilp']['ilp_count_per_h'].slice(-d.getHours())); var ilp_data = [ { x: 0, y: txt['ilp']['ilp_count_per_h'].map(i => i / 1000), type: 'line' }, { x: 0, y: Array(txt['ilp']['ilp_count_per_h'].length).fill(txt['ilp']['ilp_count_per_h'].reduce((a, b) => (a + b / 1000), 0) / txt['ilp']['ilp_count_per_h'].length), type: 'line', name: 'teho keskimäärin' } ]; Plotly.newPlot("ILP", ilp_data, ilpLayout);*/ /* var vesiLayout = { title: "Water consumption", xaxis: { title: "Day", }, yaxis: { title: "Liters per day", }, images: [ { x: 0, y: 0, sizex: 1, sizey: 1, xanchor: "left", xref: "paper", yanchor: "bottom", yref: "paper", opacity: 0.2 } ] }; var vesi_data = [ { x: 0, y: (txt['vesi_logi']['kylma_paivittain'].map(i => i.toFixed(0))), type: 'bar', name: "Cold ", marker: {color: 'blue'} }, { x: 0, y: (txt['vesi_logi']['lammin_paivittain'].map(i => i.toFixed(0))), type: 'bar', name: "Kuuma ", marker: {color: 'red'} } ]; //Plotly.newPlot("vesi", vesi_data, vesiLayout);*/ //}, //{ //x: 0, //y: (txt['ilp']['ilp_ottoteho_log'].map(i => i * 10 )), //type: 'bar', //name: "Ottoteho spot ", //marker: {color: 'orange'} //} } var data = 0; function hae_kaikki_data() { data = fetch('/nayttopaate66/kaikki_data') .then(response => response.json()) .then(data => sahkon_hinta(data)); } hae_kaikki_data(); //setInterval(hae_kaikki_data, 60000); </script>