codi-hacks / weather-station Goto Github PK
View Code? Open in Web Editor NEWEverything you need to run and monitor your own open source weather station. ⛅
Home Page: https://weather.codihacks.org/
License: Other
Everything you need to run and monitor your own open source weather station. ⛅
Home Page: https://weather.codihacks.org/
License: Other
Rather than store API results in a particular component, put the data in the Vuex store so it's globally accessible.
Once done with #14 the only seed data that should be in the migrations is the sensor_types.
Given we have the UDP socket for uploading measurements and the weather station management script coming in #14 we don't need to manage data from the API and will only need to handle GET
requests as such:
All other routes should be removed as well as the associated functions on the models (with the exception of what the UDP socket is using).
When the dashboard is empty, create an alert that displays in place of the grid to tell the user they need to open the sidebar and add some "cards" to their dashboard.
The Rust crate is currently an executable and it needs to be a library (https://learning-rust.github.io/docs/a4.cargo,crates_and_basic_project_structure.html). This way the ORM code can be re-used across multiple binaries aside from the just server executable.
Hitting the /stations route on the server I am only getting back the ID and label for the stations:
[
{
"id": "cbcb99ef-f20e-4484-93dd-ebda4a259481",
"label": "Trevor Station"
},
{
"id": "60965d1a-e02d-41a4-843c-38efa7cb334b",
"label": "R3-S6"
},
{
"id": "112fcf4c-c279-44ea-b400-6f3e3e17b472",
"label": "Ithaca"
}
]
I should also be receiving an array of sensors:
[
{
"id": "a7d6f7f3-a5b3-459a-83d7-87a3af57fe57",
"label": "Swiftcreek Reservoir",
"sensors": [
{
"id": "35072d26-5306-4b4e-b459-81758e35a202",
"alias": "signal",
"label": "signal",
"created_at": "2021-05-01T04:22:20.804463",
"updated_at": "2021-07-21T16:52:48.765878"
},
{
"id": "e67740bf-3e26-4145-8647-35f1b0914b5f",
"alias": "altitude",
"label": "altitude",
"created_at": "2021-05-01T04:22:20.804463",
"updated_at": "2021-07-21T16:52:48.770524"
},
{
"id": "f8a89dbb-57e1-442e-b19d-79a4787ffbc1",
"alias": "air_temp",
"label": "air_temp",
"created_at": "2021-05-01T04:22:20.804463",
"updated_at": "2021-07-21T16:52:48.773889"
},
{
"id": "ac7327c2-0ec6-4f4d-a55a-384cd23f519e",
"alias": "pressure",
"label": "pressure",
"created_at": "2021-05-01T04:22:20.804463",
"updated_at": "2021-07-21T16:52:48.777502"
},
{
"id": "eca63f73-0897-4cb4-ba78-adf673929e5e",
"alias": "humidity",
"label": "humidity",
"created_at": "2021-05-01T04:22:20.804463",
"updated_at": "2021-07-21T16:52:48.781044"
},
{
"id": "d61063a3-7459-4d72-a9a5-7801800f0b27",
"alias": "voltage",
"label": "voltage",
"created_at": "2021-05-01T04:22:20.804463",
"updated_at": "2021-07-21T16:52:48.784098"
}
]
}
]
Output client requests to standard out.
Here's what the app icon currently looks like:
This can be configured via the vue.config.js
- https://github.com/jcalixte/vue-pwa-asset-generator#hey-im-using-the-vue-plugin-for-pwa-where-do-i-put-my-manifest-json
This issue depends on #8 for completion.
Display some buttons in the corner of the data cards to filter the graph or average value by 1-day, 2-day, 1-week, or 90-days. https://vuetifyjs.com/en/components/button-groups/
You can zoom in on the chart by dragging the mouse across a section of the chart, narrowing the time scope even further than the selected time series. Next to the other time buttons, add a zoom reset button that appears when the chart is in a zoomed-in state that will reset the zoom when clicked (then hide again).
We need a production server and subdomain to host the API server on once it is complete. Somewhere that can handle a growing PostgreSQL database and provide direct shell access for maintenance and remote debugging.
Create a CSS flexbox that displays the sensor data in individual "cards" (Vuetify has predefined a v-card
component for this).
We need sensor type support for this in the API as well as new card types in the UI to display this information in a meaningful way.
Currently the <v-navigation-drawer>
and all its content lives inside the layout (components/Layout.vue
) but it would be cleaner to have this code live in a dedicated SideDrawer.vue
component.
If one were to bookmark cards from different stations, there is no good way to tell which is which. Something like `Ithaca's Temperature" in the corner would be nice.
Before you say? BuT tHiS iS nOt IMpOrTaNt
The dashboard will be a place the user can see only the cards/sensor data they want to see. Add a button to the corner of cards on the station page that gives the ability to pin these cards to the dashboard. The list of pinned sensors should be stored in the indexdb.
This depends on #8.
Come up with some mock data to use to get the sidebar functionality. This mock data will also model how we want the data from the api server to look so that those api server dudes will know what to send us.
Weather stations send data to the server in the form of a UDP datagram. The server needs to expose a UDP socket and parse incoming messages per the format described by the sketch.
If the voltage of a battery is ~4.2v then it gets cut off on the graph because 4.2 is currently the max peak on the chart. We should set it to something slightly higher like 4.25 or 4.3.
Client browser will block api requests across domains if we don't set a CORS policy, meaning we can't receive JSON from the server unless the server sends the appropriate HTTP headers in the response data. From the actix middleware, add some CORS header policies to the app. Something like this is probably good enough:
.wrap(middleware::DefaultHeaders::new().header("Access-Control-Allow-Methods", "GET"))
.wrap(middleware::DefaultHeaders::new().header("Access-Control-Allow-Origin", "*"))
Figure out a library we want to use and import it and make an example of it running on one of the pages.
One possible choice: https://github.com/apexcharts/vue-apexcharts
If a client connects directly to "/" then display to them a friendly html page to let them know the server is running.
You can use the include_str! macro to pull in an html file in the source code as a String.
The About page on the web app is currently one line of text. Make it not so!
A few starter ideas on what to include:
Accessible from this.$store.state.preferences.elevation
Feedback received from Reddit user Hersenbeuker:
You're using blocking Diesel database calls: https://github.com/codi-hacks/weather-station/blob/master/api-server/src/sensors/routes.rs#L16
This blocks the async runtime, you have to use the actix block functions to move these calls to the actix threadpool: https://actix.rs/docs/databases/
Create a side drawer that slides out from the right, similar to the navigation drawer that resides on the left side of the page. This will allow the user to set preferences from it such as preferred spacial units (meters/feet), preferred temperature units (celsius/fahrenheit), and color theme. This issue is specifically focused on creating the component rather than all the functionality that will reside on it.
From the bottom up, measurements belong to sensors and sensors belong to sensor_types and stations. In other words, weather stations have sensors (of a given sensors type), which in turn have measurements.
So from the SQL perspective you should have a FOREIGN_KEY definition in the measurements table:
FOREIGN KEY (sensor_id) REFERENCES sensors(id)
And in the sensors:
FOREIGN KEY (type_id) REFERENCES sensor_types(id),
FOREIGN KEY (station_id) REFERENCES stations(id)
In web-app/src/components/cards
these components share a lot of duplicate code. Some of this code such as the header text and buttons could stand to be moved into a separate component. Or perhaps a generic card component could be made without adding much complexity.
We have a Temperature card, now we need to copy the component design over to the rest of the sensor types:
Rather than exposing a public route on the API server to create stations, stations can be created and managed from a shell as needed. This will eliminate the need for authentication, at least remove the need for authentication within a 1.0 release.
This script will be located at src/bin/station
.
This is the data structure we talked about in week 6. Take the sample api on the api
branch and make it so!
Provide the user with a dropdown to change the theme. This will reside on the settings menu (#38).
See the theme generator and example implementation of loading theme variations
Edit:
So I can see two different things in one package here. The "theme" we could set different colors, e.g., a "blue" theme and "green" theme, and then on the Preferences menu have a second option for "contrast" so you can select a "light" or "dark" contrast of the theme you're using, e.g. a "light green" and "dark green".
Looking at the documentation this will probably be one of the trickier ones. For starters though you should be able to import the vuetify plugin instance and poke around:
import vuetify from '@/plugins/vuetify'
And console.log(vuetify)
to see where the dark
/light
boolean variables are inside the vuetify
object and then try toggling one of them when the contrast is changed..
Say a hooligan wants to send garbage measurements to an api server. If they knew the both the ID and private key of a station they could easily do so. To prevent this, the key is never sent as part of the datagram. Simply a hash derived from the key is used.
And that's it. There is no handshake or further encryption of the message. The weather station sends the UDP datagram and goes back to sleep as quickly as possible. It doesn't wait around and waste battery life.
What this means for the hooligan is if they don't have an id and key of a weather station, if they intercepted a datagram they would have a valid message they could send and re-send to the server over and over again to fill up the database with bogus measurements. This is a replay attack. This scenario isn't likely so I'm not labeling the issue as a critical vulnerability or anything like that. But it may be possible to fix while maintaining compatibility with the current message specification.
Let's say every message send from a weather station has a randomly-generated UUID included in it:
air_temp=23.4,humidity=62.45,id=053050d3-7fa7-438d-93f1-8285fd5eef79,uuid=469f1b70-712a-4cb6-9a87-da8eff3e90ba
#540151989
Since the hash changes every time the message changes, no two messages will have the same hash assuming each uuid is indeed unique. The api server can store this uuid in a new column (or part of the measurements' ID's in some way) and look up later when adding new measurements to make sure it hasn't seen this uuid before.
On mobile:
On desktop:
Accessible from this.$store.state.preferences.temperature
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.