- Messaggi: 14
- Ringraziamenti ricevuti 6
Postate qui domande o segnalate problemi / bug che riscontrate,
EmonCMS e wugraphs
primo messaggio, e complimenti per il software, sono riuscito ad installarlo e usarlo senza problemi con dei sensori di una stazione WH1080 (ho trovato solo i sensori per meno di 50 euro).
Per un progetto di controllo del consumo di energia/home automation io uso emoncms ( emoncms.org ) che è un prodotto nato per gestire il controllo di consumi energetici, ma che logga senza problemi anche dati di altro genere.
Ho scritto il codice per loggare dati su emoncms, cercando di seguire il sistema usato per gli altri logger (parametri di config in swpi.cfg, codice in TTLIB.py), se pensate che possa essere utile a qualcuno non ho problemi a fare una push request su github ...
Per i grafici ho usato anche io wxwugraphs, e ho notato che ha la possibilità di prendere i dati da una tabella mysql locale, invece che su weatherunderground, e ho fatto che aggiungere anche un logger per questa opzione (in aggiunta a weather underground), in questo modo si velocizza un pò la generazione delle cache per i grafici
Anche per questo, se interessa, posso fare un push
Ancora complimenti per swpi .. mi ha dato un sacco di spunti per decidermi finalmente a intraprendere un progetto che avevo in testa da un sacco di tempo ma che mi sembrava troppo complicato da realizzare ....
Allegato ScreenShot2013-05-28at12.50.33PM.png non trovato
Allegati:
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
- Messaggi: 14
- Ringraziamenti ricevuti 6
e bellissimo post di presentazione
Per le tabelle di weaherdisplay le avevo già create sul mio database e avevo messo lo sviluppo del logger in coda alle cose da fare. Anche le altre cose mi sembrano interessantissime ma ho poco tempo ora per analizzarle meglio.
Ci sentiremo questa sera.
Grazie
Tony
Si prega Accedi a partecipare alla conversazione.
Per la struttura del programma l'hai azzeccata in pieno ed uso TTLib per le funzioncine generali mentre uso dei moduli dedicati per i componenti più importanti. Per me è stato il primo progetto python e se lo dovessi rifare oggi .. forse lo rifarei completamente stravolto
Ultimamente tendo a delegare ai plugin quello che non il cuore del sistema e per esempio il logger verso emoncms lo vedrei bene in quella veste. Il logger invece verso weatherdisplay lo metterei anche magari in TTLib.
Giusto per farti un esempio ora io uso un plugin per loggare ttuto a 1 minuto ( come vedi a sisistra ) . Questo il codice :
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
##########################################################################
"""example plugin."""
import threading
import random
import datetime
import sqlite3
import sys
import subprocess
import sys
import os
import thread
import time
import globalvars
import meteodata
from TTLib import *
import RPi.GPIO as GPIO
class swpi_plugin(threading.Thread): # do not change the name of the class
def __init__(self,cfg):
self.cfg = cfg
threading.Thread.__init__(self)
###################### Plugin Initialization ################
###################### End Initialization ##################
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
i=0
while 1:
###################### Plugin run
time.sleep(60-datetime.datetime.now().second)
if ( globalvars.meteo_data.status == 0 ):
logDataToWunderground(self.cfg.WeatherUnderground_ID,self.cfg.WeatherUnderground_password)
UploadData(self.cfg)
if ( i % 5 == 0):
logData(self.cfg.serverfile,self.cfg.SMSPwd)
i = i + 1
###################### end of Plugin run
Comunque puoi gestirla come meglio credi.
Per il push dovrai però aspettare perche mi si è scazzata la kiavetta USB ed ora git mi da un "missing tree" che non sono ancora riuscito a r
isolvere.
Ciao
Tony
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
non avevo realizzato che avevi già predisposto il sistema di plugin per aggiungere funzionalità .. non credo ci saranno problemi nello spostare le funzioni in due plugin separati (anzi, anche meglio, il codice in TTlib per scrivere nella tabella mysql riapriva ogni volta la connessione al db, mentre in un suo thread la posso riusare ...)
domani mi metto e poi posto qui i due plugin, per github c'è tempo ...
Si prega Accedi a partecipare alla conversazione.
Oggi era meglio se .....
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
Guardando su questa pagina: www.susa.net/wordpress/2012/08/raspberry...an-rfm01-and-rfm12b/ ho notato che c'era anche la possibilità di monitorare il livello delle batterie (o almeno quella è la teoria) e quindi ho aggiunto la lettura di quel valore a wh1080_rf:
--- wh1080_rf/wh1080_rf.orig 2013-05-29 13:50:24.056011000 +0000
+++ wh1080_rf/wh1080_rf.c 2013-05-29 12:43:07.468011000 +0000
@@ -904,12 +904,14 @@
int direction = buf[8] & 0x0f;
char *direction_str = direction_name[direction];
+ unsigned short battery_status = ((unsigned short)(buf[8] >> 4));
printf("Station Id: %04X\n", device_id);
printf("Temperature: %0.1fC, Humidity: %d%%\n", temperature, humidity);
printf("Wind speed: %0.2f m/s, Gust Speed %0.2f m/s, %s\n", wind_avg_ms, wind_gust_ms, direction_str);
printf("Wind speed: %0.1f mph, Gust Speed %0.1f mph, %s\n", wind_avg_mph, wind_gust_mph, direction_str);
printf("Total rain: %0.1f mm\n", rain);
+ printf("Battery status: %04X \n", battery_status);
FILE *fp;
@@ -918,6 +920,7 @@
fprintf(fp,"Temperature,%0.1f,Humidity,%d\n", temperature, humidity);
fprintf(fp,"Wind_speed,%0.2f,Gust_Speed ,%0.2f,%s,%d\n", wind_avg_ms*3.6, wind_gust_ms*3.6, direction_str,direction);
fprintf(fp,"Total_rain,%0.1f \n", rain);
+ fprintf(fp,"Battery_status,%04X \n", battery_status);
fclose(fp);
}
Questo è il plugin per loggare su emoncms:
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
##########################################################################
"""emoncmslog plugin."""
import threading
import random
import datetime
import sqlite3
import sys
import subprocess
import sys
import os
import thread
import time
import requests
import globalvars
import meteodata
from TTLib import *
class swpi_plugin(threading.Thread): # do not change the name of the class
def __init__(self,cfg):
self.cfg = cfg
threading.Thread.__init__(self)
###################### Plugin Initialization ################
###################### End Initialization ##################
def logDataToEmonCMS(self):
if ( globalvars.meteo_data.last_measure_time == None):
return
delay = (datetime.datetime.now() - globalvars.meteo_data.last_measure_time)
delay_seconds = int(delay.total_seconds())
if ( delay_seconds > 120 ):
return
# Assign inputs to a node group /emoncms/input/post.json?node=1&csv=100,200,300
# Inputs we want to log:
#
# globalvars.meteo_data.hum_out = hum
# globalvars.meteo_data.temp_out = temp
# globalvars.meteo_data.wind_ave = Wind_speed
# globalvars.meteo_data.wind_gust = Gust_Speed
# globalvars.meteo_data.wind_dir = dire*22.5
# globalvars.meteo_data.wind_dir_code = dir_code
# globalvars.meteo_data.rain = rain
# globalvars.meteo_data.winDayMin
# globalvars.meteo_data.rain_rate
# globalvars.meteo_data.wind_chill
# globalvars.meteo_data.temp_apparent
# globalvars.meteo_data.dew_point
# globalvars.meteo_data.winDayMax
# globalvars.meteo_data.winDayGustMin
# globalvars.meteo_data.winDayGustMax
# globalvars.meteo_data.TempOutMin
# globalvars.meteo_data.TempOutMax
# globalvars.meteo_data.wind_dir_ave
# globalvars.meteo_data.rain_rate_24h
# globalvars.meteo_data.rain_rate_1h
# globalvars.meteo_data.battery
#
param_list = []
param_list.append("{:.2f}".format((globalvars.meteo_data.hum_out)))
param_list.append("{:.2f}".format((globalvars.meteo_data.temp_out)))
param_list.append("{:.2f}".format((globalvars.meteo_data.temp_apparent)))
param_list.append("{:.2f}".format((globalvars.meteo_data.TempOutMin)))
param_list.append("{:.2f}".format((globalvars.meteo_data.TempOutMax)))
param_list.append("{:.4f}".format((globalvars.meteo_data.rain)))
param_list.append("{:.4f}".format((globalvars.meteo_data.rain_rate)))
if globalvars.meteo_data.rain_rate_1h != None : param_list.append("{:.4f}".format((globalvars.meteo_data.rain_rate_1h)))
else :
param_list.append("0");
if globalvars.meteo_data.rain_rate_24h != None : param_list.append("{:.4f}".format((globalvars.meteo_data.rain_rate_24h)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_ave != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_ave)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_gust != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_gust)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_dir != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_dir)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_chill != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_chill)))
else :
param_list.append("0");
if globalvars.meteo_data.dew_point != None : param_list.append("{:.2f}".format((globalvars.meteo_data.dew_point)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayMin != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayMin)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayMax != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayMax)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayGustMin != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayGustMin)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayGustMax != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayGustMax)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_dir_ave != None : param_list.append("{:.4f}".format((globalvars.meteo_data.wind_dir_ave)))
else :
param_list.append("0");
if globalvars.meteo_data.battery != None : param_list.append(str(globalvars.meteo_data.battery))
else :
param_list.append("-1");
parameters = '?apikey=' + str(self.cfg.Emoncms_apikey) +'&node='+str(self.cfg.Emoncms_nodeId)+'&csv='+','.join(param_list)
#print parameters
log("logToEmonCMS - url: " + self.cfg.Emoncms_serverfile + " - Parameters: " + parameters)
try:
r = requests.get(self.cfg.Emoncms_serverfile+parameters,timeout=10)
msg = r.text.splitlines()
log("Log to EmonCms Result: " + msg[0])
except Exception,e:
log( "Error Logging to EmonCms : " + str(e) )
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
if (self.cfg.Emoncms_logdata):
while 1:
###################### Plugin run
time.sleep(60-datetime.datetime.now().second)
if ( globalvars.meteo_data.status == 0 ):
if ( globalvars.meteo_data.last_measure_time != None and globalvars.meteo_data.status == 0 ) :
log("Logging data to EmonCMS plugin ...")
self.logDataToEmonCMS()
else:
log("Stopping plugin : %s" % sys.modules[__name__])
###################### end of Plugin run
e questo è il plugin per loggare su tabella che wugraphs può leggere direttamente:
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
##########################################################################
"""wugraphslog plugin."""
import threading
import random
import datetime
import sqlite3
import sys
import subprocess
import sys
import os
import thread
import time
import globalvars
import meteodata
from TTLib import *
import MySQLdb
class swpi_plugin(threading.Thread): # do not change the name of the class
def mysqlFormatString(self,value,formatstring):
if (value is None):
value = 0
else:
value = formatstring.format((value))
return value
def logDataToWugraphs(self):
if ( globalvars.meteo_data.last_measure_time == None):
return
delay = (datetime.datetime.now() - globalvars.meteo_data.last_measure_time)
delay_seconds = int(delay.total_seconds())
if ( delay_seconds > 120 ):
return
cur = self.mysqlDB.cursor();
sql = "INSERT INTO "+ self.cfg.wugraphs_table + " (datetime, outdoor_humidity, temperature, rain_rate, wind_direction, average_windspeed, gust_windspeed, dew_point_temperature ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
datetimeMeas = globalvars.meteo_data.last_measure_time
hum_out = self.mysqlFormatString(globalvars.meteo_data.hum_out, "{:.2f}")
temp_out = self.mysqlFormatString(globalvars.meteo_data.temp_out, "{:.2f}")
rain_rate = self.mysqlFormatString(globalvars.meteo_data.rain_rate, "{:.4f}")
rain_rate_1h = self.mysqlFormatString(globalvars.meteo_data.rain_rate_1h, "{:.4f}")
wind_dir = self.mysqlFormatString(globalvars.meteo_data.wind_dir, "{:.2f}")
wind_ave = self.mysqlFormatString(globalvars.meteo_data.wind_ave, "{:.2f}")
wind_gust = self.mysqlFormatString(globalvars.meteo_data.wind_gust, "{:.2f}")
dew_point = self.mysqlFormatString(globalvars.meteo_data.dew_point, "{:.2f}")
#print parameters
log("logToWugraphs ...")
try:
cur.execute(sql,(datetimeMeas,hum_out,temp_out,rain_rate,wind_dir,wind_ave,wind_gust,dew_point))
self.mysqlDB.commit()
except MySQLdb.Error, e:
log( "Error Logging to Wugraphs : " )
try:
print "MySQL Error [%d]: %s" % (e.args[0], e.args[1])
except IndexError:
print "MySQL Error: %s" % str(e)
def __init__(self,cfg):
self.cfg = cfg
self.mysqlDB = None
threading.Thread.__init__(self)
###################### Plugin Initialization ################
###################### End Initialization ##################
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
if (self.cfg.WeatherUnderground_logdata):
try:
self.mysqlDB = MySQLdb.connect(host=self.cfg.wugraphs_dbhost,user=self.cfg.wugraphs_user, passwd=self.cfg.wugraphs_password, db=self.cfg.wugraphs_schema, port=int(self.cfg.wugraphs_dbport))
except Exception,e:
log("Error connecting to Wugraphs db : " + str(e))
return
while 1:
###################### Plugin run
time.sleep(60-datetime.datetime.now().second)
if ( globalvars.meteo_data.status == 0 ):
if ( globalvars.meteo_data.last_measure_time != None and globalvars.meteo_data.status == 0 ) :
log("Logging data to wugraphs plugin")
self.logDataToWugraphs()
log("Logging data to wugraphs plugin: Success!")
else:
log("Stopping plugin : %s" % sys.modules[__name__])
###################### end of Plugin run
I due plugin prendono i parametri di configurazione da swpi.cfg:
[Emoncms]
emoncms_logdata = true
emoncms_apikey = <apikey>
emoncms_serverfile = http://localhost/emoncms/input/post.json
emoncms_nodeid = 9999
[Wugraphs]
wugraphs_logdata = true
wugraphs_dbhost = localhost
wugraphs_dbport = 3306
wugraphs_user = myuser
wugraphs_password = mypass
wugraphs_schema = weather
wugraphs_table = wugraphs
e queste sono le modifiche a config.py per leggere i valori di config:
#[EmonCMS]
self.Emoncms_logdata = config.getboolean('Emoncms', 'Emoncms_logdata',False)
self.Emoncms_apikey = config.get('Emoncms', 'Emoncms_apikey',"KCASANFR5")
self.Emoncms_serverfile = config.get('Emoncms', 'Emoncms_serverfile',"http://localhost/emoncms/post")
self.Emoncms_nodeId = config.get('Emoncms', 'Emoncms_nodeId',1001)
#[Wugraphs]
self.wugraphs_logdata = config.getboolean('Wugraphs', 'wugraphs_logdata',False)
self.wugraphs_dbhost = config.get('Wugraphs', 'wugraphs_dbhost',"localhost")
self.wugraphs_dbport = config.get('Wugraphs', 'wugraphs_dbport',3306)
self.wugraphs_user = config.get('Wugraphs', 'wugraphs_user',"user")
self.wugraphs_password = config.get('Wugraphs', 'wugraphs_password',"user")
self.wugraphs_schema = config.get('Wugraphs', 'wugraphs_schema',"user")
self.wugraphs_table = config.get('Wugraphs', 'wugraphs_table',"user")
La tabella wugraphs (con qualche colonna in più di quelle realmente necessarie, per usi futuri):
CREATE TABLE `wugraphs` (
`average_windspeed` float DEFAULT '0',
`wind_direction` smallint(3) DEFAULT '0',
`gust_windspeed` float DEFAULT '0',
`temperature` float DEFAULT '0',
`outdoor_humidity` float DEFAULT '0',
`barometer` float DEFAULT '0',
`daily_rainfall` float DEFAULT '0',
`rain_rate` float DEFAULT '0',
`indoor_temperature` float DEFAULT '0',
`indoor_humidity` float DEFAULT '0',
`actual_solar_reading` int(11) DEFAULT '0',
`max_daily_temperature` float DEFAULT '0',
`min_daily_temperature` float DEFAULT '0',
`max_gust_current_day` float DEFAULT '0',
`dew_point_temperature` float DEFAULT '0',
`datetime` datetime DEFAULT NULL,
`current_weather_desc` text,
`davis_vp_uv` float DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Si prega Accedi a partecipare alla conversazione.
Due righe di spiegazione su EmonCMS: è un cms che si scarica-carica sul proprio server o ci si registra e riceve i dati degli utenti ? Hai un link di demo funzionante? Che vantaggi ha ?
Si prega Accedi a partecipare alla conversazione.
La parte rf la includo anche io nelle prossime release.
Sono un piccolo problema da risolvere con la configurazione.
Trattandosi di plugin non vorrei modificare il file config.py e preferirei che ciascun plugin gestisca la sua configurazione con un file separato o magari anche all'interno dello stesso plugin ( che forse è anche più semplice )
Così chi lo vuole utilizzare se lo copia nella cartella plugin e lo configura direttamente. Questo mi eviterebbe completamente di modificare il "core" del programma ed i pluging sarebbero tali a tutti gli effetti.
Che ne pensi ?
TT
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
per quanto riguarda la config .. è una bella rana ... il posto giusto sarebbe nella config generale, e che il plugin fosse in grado in qualche modo di leggerselo ... i valori direttamente nel plugin non mi piacciono molto, ma sono la seconda opzione, sempre meglio che dover modificare ogni volta config.py ... non sono per niente esperto di python ...
Un alternativa sarebbe fare in modo che la classe config fornisse un metodo tipo loadSection(nome) .. in quel modo i parametri potrebbero andare nel file di configurazione, e il plugin dovrebbe solo importare config e caricare la sezione che gli appartiene ....
Per quanto riguarda emoncms, può essere installato in locale (php + mysql) o usato nella versione pubblica su emoncms.org (la registrazione e gratuita) anzi, la versione locale può anche rilanciare i dati su una seconda versione (pubblica o di nuovo custom, non importa)
Un esempio: baptistegaultier.fr/emoncms/baptiste
I grafici sono zoomabili per vedere i consumi giornalieri/orari
Si prega Accedi a partecipare alla conversazione.
Resto dell'idea che un pluging debba funzionare senza l'intervento o modifica del programma principale ( compresa la sua configurazione ).
Se non ti piace configurare direttamente nel file del plugin ( lo dicevo per semplificarti la vita ) allora l'unica alternativa è un emoncms.cfg e wugraph.cfg da mettere nella cartella plugin insieme ai 2 py. Nell'inizializzazione del plugin dovrai parsarti i 2 file usando un semplice ConfigParser.SafeConfigParser
Non c'è neanche bisogno che ti derivi una tua classe come ho fatto io in config.py che è per me un meccanismo per non dover chiedere ad ogni aggiunta di chiavi di dover modificare manualmente il file di conf .. le tue sono fisse.
Sto preparando nella sezione download un elenco di plugin e metterò anche i tuoi. Preferirei , piuttosto che copiarli sul mio sito, mettere un link al tuo ( se lo hai ) in modo che puoi gestire gli aggiornamenti autonomamente .. un pò come ha fatto Alessandro per i template web . Altrimenti nessun problema ad ospitarli qui.
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
Per dove mettere il codice, direi sul mio account github, nessun problema.
Sto ancora facendo delle piccole modifiche, sto avendo problemi con il timestamp con cui wh1080_rf logga i dati, è circa 30 minuti nel futuro e non riesco a capire come sia possibile (ho lo stesso problema anche se faccio un semplice touch di un file ...)
Ho anche cambiato leggermente la logica di logging per fare in modo di non loggare due volte la stessa misura .. e maledetto python per quei cavolo di : dopo gli if ... e anche per le tabulazioni
Appena sono in una condizione stabile posto la nuova versione
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
ho cambiato la logica di loggging in entrambi i plugin per inviare dati ai log solo quando la misura è effettivamente cambiata.
Ho anche reso configurabile il tempo tra cui effettuare il check per il cambio della misura (nel caso della WH1080 l'intervallo minimo è 48 secondi, ma magari in altri casi sono disponibili più o meno dati)
emoncms plugin:
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
# Emoncmslog plugin logs meteo data from sint wind pi to emoncms (http://emoncms.org/) using
# the provided api (http://emoncms.org/site/docs/inputsandfeeds)
#
# In order to successfully log data three parameters are required:
#
# emoncms_serverfile: URL to emoncms post.json page
# emoncms_apikey: WRITE API (available from emoncms interface at the url /emoncms/input/api)
# emoncms_modeid: node id to identify the meteo data in the input config page
#
#
##########################################################################
"""emoncmslog plugin."""
import threading
import random
import datetime
import sys
import subprocess
import sys
import os
import thread
import time
import requests
import globalvars
import meteodata
from TTLib import *
class swpi_plugin(threading.Thread): # do not change the name of the class
def __init__(self,cfg):
###################### Plugin Initialization ################
self.cfg = cfg
self.last_measure_time = None
self.sleep_time=30
self.emoncms_apikey = "apikey"
self.emoncms_serverfile = "http://localhost/emoncms/input/post.json"
self.emoncms_nodeid = 9999
threading.Thread.__init__(self)
###################### End Initialization ##################
def logDataToEmonCMS(self):
if ( globalvars.meteo_data.last_measure_time == None):
return
if(globalvars.meteo_data.last_measure_time == self.last_measure_time):
log("Emoncmsplugin: No change detected")
return
# Assign inputs to a node group /emoncms/input/post.json?node=1&csv=100,200,300
# Inputs we want to log:
#
# globalvars.meteo_data.hum_out = hum
# globalvars.meteo_data.temp_out = temp
# globalvars.meteo_data.wind_ave = Wind_speed
# globalvars.meteo_data.wind_gust = Gust_Speed
# globalvars.meteo_data.wind_dir = dire*22.5
# globalvars.meteo_data.wind_dir_code = dir_code
# globalvars.meteo_data.rain = rain
# globalvars.meteo_data.winDayMin
# globalvars.meteo_data.rain_rate
# globalvars.meteo_data.wind_chill
# globalvars.meteo_data.temp_apparent
# globalvars.meteo_data.dew_point
# globalvars.meteo_data.winDayMax
# globalvars.meteo_data.winDayGustMin
# globalvars.meteo_data.winDayGustMax
# globalvars.meteo_data.TempOutMin
# globalvars.meteo_data.TempOutMax
# globalvars.meteo_data.wind_dir_ave
# globalvars.meteo_data.rain_rate_24h
# globalvars.meteo_data.rain_rate_1h
# globalvars.meteo_data.battery
#
self.last_measure_time = globalvars.meteo_data.last_measure_time
param_list = []
param_list.append("{:.2f}".format((globalvars.meteo_data.hum_out)))
param_list.append("{:.2f}".format((globalvars.meteo_data.temp_out)))
param_list.append("{:.2f}".format((globalvars.meteo_data.temp_apparent)))
param_list.append("{:.2f}".format((globalvars.meteo_data.TempOutMin)))
param_list.append("{:.2f}".format((globalvars.meteo_data.TempOutMax)))
param_list.append("{:.4f}".format((globalvars.meteo_data.rain)))
param_list.append("{:.4f}".format((globalvars.meteo_data.rain_rate)))
if globalvars.meteo_data.rain_rate_1h != None : param_list.append("{:.4f}".format((globalvars.meteo_data.rain_rate_1h)))
else :
param_list.append("0");
if globalvars.meteo_data.rain_rate_24h != None : param_list.append("{:.4f}".format((globalvars.meteo_data.rain_rate_24h)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_ave != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_ave)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_gust != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_gust)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_dir != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_dir)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_chill != None : param_list.append("{:.2f}".format((globalvars.meteo_data.wind_chill)))
else :
param_list.append("0");
if globalvars.meteo_data.dew_point != None : param_list.append("{:.2f}".format((globalvars.meteo_data.dew_point)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayMin != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayMin)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayMax != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayMax)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayGustMin != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayGustMin)))
else :
param_list.append("0");
if globalvars.meteo_data.winDayGustMax != None : param_list.append("{:.2f}".format((globalvars.meteo_data.winDayGustMax)))
else :
param_list.append("0");
if globalvars.meteo_data.wind_dir_ave != None : param_list.append("{:.4f}".format((globalvars.meteo_data.wind_dir_ave)))
else :
param_list.append("0");
if globalvars.meteo_data.battery != None : param_list.append(str(globalvars.meteo_data.battery))
else :
param_list.append("-1");
parameters = '?apikey=' + str(self.emoncms_apikey) +'&node='+str(self.emoncms_nodeid)+'&csv='+','.join(param_list)
#print parameters
log("logToEmonCMS - url: " + self.emoncms_serverfile + " - Parameters: " + parameters)
try:
r = requests.get(self.emoncms_serverfile+parameters,timeout=10)
msg = r.text.splitlines()
log("Log to EmonCms Result: " + msg[0])
except Exception,e:
log( "Error Logging to EmonCms : " + str(e) )
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
while 1:
###################### Plugin run
time.sleep(self.sleep_time)
if ( globalvars.meteo_data.status == 0 ):
if ( globalvars.meteo_data.last_measure_time != None and globalvars.meteo_data.status == 0 ) :
log("Logging data to EmonCMS plugin ...")
self.logDataToEmonCMS()
###################### end of Plugin run
wugraphslog plugin:
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
##########################################################################
"""wugraphslog plugin."""
import threading
import random
import datetime
import sqlite3
import sys
import subprocess
import sys
import os
import thread
import time
import globalvars
import meteodata
from TTLib import *
import MySQLdb
class swpi_plugin(threading.Thread): # do not change the name of the class
def __init__(self,cfg):
self.cfg = cfg
self.mysqlDB = None
self.last_measure_time = None
self.sleep_time=30
self.wugraphs_dbhost = "localhost"
self.wugraphs_dbport = 3306
self.wugraphs_user = "user"
self.wugraphs_password = "pass"
self.wugraphs_schema = "weather"
self.wugraphs_table = "wugraphs"
threading.Thread.__init__(self)
###################### Plugin Initialization ################
###################### End Initialization ##################
def mysqlFormatString(self,value,formatstring):
if (value is None):
value = 0
else:
value = formatstring.format((value))
return value
def logDataToWugraphs(self):
if ( globalvars.meteo_data.last_measure_time == None):
return
if(globalvars.meteo_data.last_measure_time == self.last_measure_time):
log("logToWugraphs: No change detected")
return
self.last_measure_time = globalvars.meteo_data.last_measure_time
cur = self.mysqlDB.cursor();
sql = "INSERT INTO "+ self.wugraphs_table + " (datetime, outdoor_humidity, temperature, rain_rate, wind_direction, average_windspeed, gust_windspeed, dew_point_temperature ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
datetimeMeas = globalvars.meteo_data.last_measure_time
hum_out = self.mysqlFormatString(globalvars.meteo_data.hum_out, "{:.2f}")
temp_out = self.mysqlFormatString(globalvars.meteo_data.temp_out, "{:.2f}")
rain_rate = self.mysqlFormatString(globalvars.meteo_data.rain_rate, "{:.4f}")
rain_rate_1h = self.mysqlFormatString(globalvars.meteo_data.rain_rate_1h, "{:.4f}")
wind_dir = self.mysqlFormatString(globalvars.meteo_data.wind_dir, "{:.2f}")
wind_ave = self.mysqlFormatString(globalvars.meteo_data.wind_ave, "{:.2f}")
wind_gust = self.mysqlFormatString(globalvars.meteo_data.wind_gust, "{:.2f}")
dew_point = self.mysqlFormatString(globalvars.meteo_data.dew_point, "{:.2f}")
#print parameters
log("logToWugraphs ...")
try:
cur.execute(sql,(datetimeMeas,hum_out,temp_out,rain_rate,wind_dir,wind_ave,wind_gust,dew_point))
self.mysqlDB.commit()
except MySQLdb.Error, e:
log( "Error Logging to Wugraphs : " )
try:
print "MySQL Error [%d]: %s" % (e.args[0], e.args[1])
except IndexError:
print "MySQL Error: %s" % str(e)
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
try:
self.mysqlDB = MySQLdb.connect(host=self.wugraphs_dbhost,user=self.wugraphs_user, passwd=self.wugraphs_password, db=self.wugraphs_schema, port=int(self.wugraphs_dbport))
except Exception,e:
log("Error connecting to Wugraphs db : " + str(e))
return
while 1:
###################### Plugin run
time.sleep(self.sleep_time)
if ( globalvars.meteo_data.status == 0 ):
if ( globalvars.meteo_data.last_measure_time != None and globalvars.meteo_data.status == 0 ) :
log("Logging data to wugraphs plugin")
self.logDataToWugraphs()
log("Logging data to wugraphs plugin: Success!")
###################### end of Plugin run
Si prega Accedi a partecipare alla conversazione.
Si prega Accedi a partecipare alla conversazione.
Traceback (most recent call last):
File "swpi.py", line 684, in <module>
pl.loadAll()
File "/home/pi/swpi/pluginmanager.py", line 33, in loadAll
mod = importlib.import_module(name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "./plugins/wugraph.py", line 27, in <module>
import MySQLdb
ImportError: No module named MySQLdb
Come faccio ad importare il mudulo MySQLdb ?
Si prega Accedi a partecipare alla conversazione.
Adesso per ho un errore di connessione al db:
Error connecting to Wugraphs db : (1045, "Access denied for user 'grechiit_meteo'@'2.231.70.26' (using password: YES)")
Eppure son sicuro che i parametri son giusti perchè sono gli stessi che usavo per il logger php.
Che il mio server non accetti connessioni dirette al db dall'esterno?
self.wugraphs_dbhost = "grechi.it"
self.wugraphs_dbport = 3306
self.wugraphs_user = "grechiit_meteo"
self.wugraphs_password = "********"
self.wugraphs_schema = "grechiit_meteo"
self.wugraphs_table = "wugraphs"
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
Probabilmente dovresti combinare la funzionalità di wugraphs e quella dell url uploader, e fare un post ad una tua pagina php che vada a scrivere su mysql direttamente dal tuo sito in hosting ....
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
Si prega Accedi a partecipare alla conversazione.
Per ora lascio cosi e vedo quanto dura... in fondo il cambio ip avviene abbastanza raramente.
Il logger php interno preferirei evitarlo perchè mi sovraccarica parecchio il server, visto che viene chiamato ogni minuto.
Settando tutto poi funziona e visualizzo i wugraphs orari
Ho notato una cosa che probabilmente è una dimenticanza- Nelle tabelle wugraphs non si riempiono i dati relativi a temperatura/umidità interna (anche se non importa più di tanto) e pressione. Andrebbero aggiunti al plugin!
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
prova questo ...
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
##########################################################################
"""wugraphslog plugin."""
import threading
import random
import datetime
import sqlite3
import sys
import subprocess
import sys
import os
import thread
import time
import globalvars
import meteodata
from TTLib import *
import MySQLdb
class swpi_plugin(threading.Thread): # do not change the name of the class
def __init__(self,cfg):
self.cfg = cfg
self.mysqlDB = None
self.last_measure_time = None
self.sleep_time=30
self.wugraphs_dbhost = "localhost"
self.wugraphs_dbport = 3306
self.wugraphs_user = "root"
self.wugraphs_password = "raspberry"
self.wugraphs_schema = "weather"
self.wugraphs_table = "wugraphs"
threading.Thread.__init__(self)
###################### Plugin Initialization ################
###################### End Initialization ##################
def mysqlFormatString(self,value,formatstring):
if (value is None):
value = 0
else:
value = formatstring.format((value))
return value
def logDataToWugraphs(self):
if ( globalvars.meteo_data.last_measure_time == None):
return
if(globalvars.meteo_data.last_measure_time == self.last_measure_time):
log("logToWugraphs: No change detected")
return
self.last_measure_time = globalvars.meteo_data.last_measure_time
cur = self.mysqlDB.cursor();
sql = "INSERT INTO "+ self.wugraphs_table + " (datetime, outdoor_humidity, temperature, rain_rate, wind_direction, average_windspeed, gust_windspeed, dew_point_temperature,indoor_humidity,indoor_temperature ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
datetimeMeas = globalvars.meteo_data.last_measure_time
hum_out = self.mysqlFormatString(globalvars.meteo_data.hum_out, "{:.2f}")
temp_out = self.mysqlFormatString(globalvars.meteo_data.temp_out, "{:.2f}")
rain_rate = self.mysqlFormatString(globalvars.meteo_data.rain_rate, "{:.4f}")
rain_rate_1h = self.mysqlFormatString(globalvars.meteo_data.rain_rate_1h, "{:.4f}")
wind_dir = self.mysqlFormatString(globalvars.meteo_data.wind_dir, "{:.2f}")
wind_ave = self.mysqlFormatString(globalvars.meteo_data.wind_ave, "{:.2f}")
wind_gust = self.mysqlFormatString(globalvars.meteo_data.wind_gust, "{:.2f}")
dew_point = self.mysqlFormatString(globalvars.meteo_data.dew_point, "{:.2f}")
hum_in = self.mysqlFormatString(globalvars.meteo_data.hum_in, "{:.2f}")
temp_in = self.mysqlFormatString(globalvars.meteo_data.temp_in, "{:.2f}")
#print parameters
log("logToWugraphs ...")
try:
cur.execute(sql,(datetimeMeas,hum_out,temp_out,rain_rate,wind_dir,wind_ave,wind_gust,dew_point,hum_in,temp_in))
self.mysqlDB.commit()
except MySQLdb.Error, e:
log( "Error Logging to Wugraphs : " )
try:
print "MySQL Error [%d]: %s" % (e.args[0], e.args[1])
except IndexError:
print "MySQL Error: %s" % str(e)
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
try:
self.mysqlDB = MySQLdb.connect(host=self.wugraphs_dbhost,user=self.wugraphs_user, passwd=self.wugraphs_password, db=self.wugraphs_schema, port=int(self.wugraphs_dbport))
except Exception,e:
log("Error connecting to Wugraphs db : " + str(e))
return
while 1:
###################### Plugin run
time.sleep(self.sleep_time)
if ( globalvars.meteo_data.status == 0 ):
if ( globalvars.meteo_data.last_measure_time != None and globalvars.meteo_data.status == 0 ) :
log("Logging data to wugraphs plugin")
self.logDataToWugraphs()
log("Logging data to wugraphs plugin: Success!")
###################### end of Plugin run
Si prega Accedi a partecipare alla conversazione.
per completezza ho aggiunto anche pressione relativa, temp out max e min, wind gust max
Ho inoltre corretto un errore nel daily_rainfall, che mancava e veniva invertito con il rain_rate, che invece corrisponde al rain_rate_1h
###########################################################################
# Sint Wind PI
# Copyright 2012 by Tonino Tarsi <tony.tarsi@gmail.com>
#
# USB comunication based pywws by 'Jim Easterbrook' <jim@jim-easterbrook.me.uk>
# Please refer to the LICENSE file for conditions
# Visit http://www.vololiberomontecucco.it
#
##########################################################################
"""wugraphslog plugin."""
import threading
import random
import datetime
import sqlite3
import sys
import subprocess
import sys
import os
import thread
import time
import globalvars
import meteodata
from TTLib import *
import MySQLdb
class swpi_plugin(threading.Thread): # do not change the name of the class
def __init__(self,cfg):
self.cfg = cfg
self.mysqlDB = None
self.last_measure_time = None
self.sleep_time=30
self.wugraphs_dbhost = "localhost"
self.wugraphs_dbport = 3306
self.wugraphs_user = "root"
self.wugraphs_password = "raspberry"
self.wugraphs_schema = "weather"
self.wugraphs_table = "wugraphs"
threading.Thread.__init__(self)
###################### Plugin Initialization ################
###################### End Initialization ##################
def mysqlFormatString(self,value,formatstring):
if (value is None):
value = 0
else:
value = formatstring.format((value))
return value
def logDataToWugraphs(self):
if ( globalvars.meteo_data.last_measure_time == None):
return
if(globalvars.meteo_data.last_measure_time == self.last_measure_time):
log("logToWugraphs: No change detected")
return
self.last_measure_time = globalvars.meteo_data.last_measure_time
cur = self.mysqlDB.cursor();
sql = "INSERT INTO "+ self.wugraphs_table + " (datetime, outdoor_humidity, temperature, daily_rainfall, rain_rate, wind_direction, average_windspeed, gust_windspeed, dew_point_temperature, indoor_humidity, indoor_temperature, barometer, max_daily_temperature, min_daily_temperature, max_gust_current_day ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
datetimeMeas = globalvars.meteo_data.last_measure_time
hum_out = self.mysqlFormatString(globalvars.meteo_data.hum_out, "{:.2f}")
temp_out = self.mysqlFormatString(globalvars.meteo_data.temp_out, "{:.2f}")
rain_rate = self.mysqlFormatString(globalvars.meteo_data.rain_rate, "{:.4f}")
rain_rate_1h = self.mysqlFormatString(globalvars.meteo_data.rain_rate_1h, "{:.4f}")
wind_dir = self.mysqlFormatString(globalvars.meteo_data.wind_dir, "{:.2f}")
wind_ave = self.mysqlFormatString(globalvars.meteo_data.wind_ave, "{:.2f}")
wind_gust = self.mysqlFormatString(globalvars.meteo_data.wind_gust, "{:.2f}")
dew_point = self.mysqlFormatString(globalvars.meteo_data.dew_point, "{:.2f}")
hum_in = self.mysqlFormatString(globalvars.meteo_data.hum_in, "{:.2f}")
temp_in = self.mysqlFormatString(globalvars.meteo_data.temp_in, "{:.2f}")
rel_pressure = self.mysqlFormatString(globalvars.meteo_data.rel_pressure, "{:.2f}")
temp_out_max = self.mysqlFormatString(globalvars.meteo_data.TempOutMax, "{:.2f}")
temp_out_min = self.mysqlFormatString(globalvars.meteo_data.TempOutMin, "{:.2f}")
winDayGustMax = self.mysqlFormatString(globalvars.meteo_data.winDayGustMax, "{:.2f}")
#print parameters
log("logToWugraphs ...")
try:
cur.execute(sql,(datetimeMeas,hum_out,temp_out,rain_rate,rain_rate_1h,wind_dir,wind_ave,wind_gust,dew_point,hum_in,temp_in,rel_pressure,temp_out_max,temp_out_min,winDayGustMax))
self.mysqlDB.commit()
except MySQLdb.Error, e:
log( "Error Logging to Wugraphs : " )
try:
print "MySQL Error [%d]: %s" % (e.args[0], e.args[1])
except IndexError:
print "MySQL Error: %s" % str(e)
def run(self):
log("Starting plugin : %s" % sys.modules[__name__])
try:
self.mysqlDB = MySQLdb.connect(host=self.wugraphs_dbhost,user=self.wugraphs_user, passwd=self.wugraphs_password, db=self.wugraphs_schema, port=int(self.wugraphs_dbport))
except Exception,e:
log("Error connecting to Wugraphs db : " + str(e))
return
while 1:
###################### Plugin run
time.sleep(self.sleep_time)
if ( globalvars.meteo_data.status == 0 ):
if ( globalvars.meteo_data.last_measure_time != None and globalvars.meteo_data.status == 0 ) :
log("Logging data to wugraphs plugin")
self.logDataToWugraphs()
log("Logging data to wugraphs plugin: Success!")
###################### end of Plugin run
Si prega Accedi a partecipare alla conversazione.
- jackie2_it
- Offline
- Expert Boarder
- Messaggi: 147
- Ringraziamenti ricevuti 1
La mia stazione meteo www.ilampidigenio.it/stazione-meteo/
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
shop.openenergymonitor.com/100a-max-clip-on-current-sensor-ct/
collegati ad un arduino:
shop.openenergymonitor.com/emontx-868mhz-kit-europe-only/
che a sua volta rimanda i dati al raspberry, che li riceve tramite un modulo RFM12:
shop.openenergymonitor.com/rfm12pi-raspb...n-board-kit-868-mhz/
Si prega Accedi a partecipare alla conversazione.
Forse mi è sfuggito ma mi manca il link al tuo github da mettere come riferimento ai sorgenti.
Si prega Accedi a partecipare alla conversazione.
- jackie2_it
- Offline
- Expert Boarder
- Messaggi: 147
- Ringraziamenti ricevuti 1
madmatt ha scritto: Ciao, i sensori sono questi:
shop.openenergymonitor.com/100a-max-clip-on-current-sensor-ct/
collegati ad un arduino:
shop.openenergymonitor.com/emontx-868mhz-kit-europe-only/
che a sua volta rimanda i dati al raspberry, che li riceve tramite un modulo RFM12:
shop.openenergymonitor.com/rfm12pi-raspb...n-board-kit-868-mhz/
Ma l'arduino che hai indicato nel link non è un classico Arduino ma una versione modificata giusto?
La mia stazione meteo www.ilampidigenio.it/stazione-meteo/
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
@jackie: e' un arduino con dell'elettronica aggiunta per supportare tre sensori amperometrici, uno di voltaggio, uno o piu' di temperatura, uno ottico e un modulo rfm12 sul pcb, ma si programma con l'ide di arduino (e' un arduino uno)
Viene anche fornito con una libreria che rende banale l'uso dei sensori .... Ma nulla ti impedisce di usare un'arduino standard e solo i sensori a patto che ti fai la parte elettronica e la parte di programmazione per conto tuo ... Il sensore amperometrico ad esempio restituisce una corrente prioporzionale alla corrente che misura, quindi in teoria sapendo il voltaggio e con qualche moltiplicazione potresti collegarlo direttamente ( o quasi, non ne so praticamente nulla di elettronica...) and un ingresso analogico e partire da li'
Si prega Accedi a partecipare alla conversazione.
- Messaggi: 14
- Ringraziamenti ricevuti 6
Si prega Accedi a partecipare alla conversazione.
questo è il link dei grafici www.trussino.com/swpi/wugraphs.php
Ciao
Si prega Accedi a partecipare alla conversazione.
Dove posso trovare una guida per capire come fare?
Si prega Accedi a partecipare alla conversazione.