mirror of
https://github.com/FliegendeWurst/raspi-oled.git
synced 2024-11-21 09:54:59 +00:00
Colored events + ...
This commit is contained in:
parent
422221d97e
commit
90d04aeb10
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
events_weekly.json
|
||||||
|
events.json
|
||||||
|
sensors.db
|
113
Cargo.lock
generated
113
Cargo.lock
generated
@ -37,6 +37,12 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4"
|
checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@ -110,6 +116,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chunked_transfer"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -179,15 +191,6 @@ dependencies = [
|
|||||||
"adler32",
|
"adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dht-hal"
|
|
||||||
version = "0.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eb5423e6132fe67189d1aeac8a7412e7d09816a7374e22201a49a2d5081c8549"
|
|
||||||
dependencies = [
|
|
||||||
"embedded-hal 0.2.7",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "display-interface"
|
name = "display-interface"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -315,6 +318,16 @@ dependencies = [
|
|||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "form_urlencoded"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
|
||||||
|
dependencies = [
|
||||||
|
"matches",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.21"
|
version = "0.3.21"
|
||||||
@ -417,6 +430,17 @@ dependencies = [
|
|||||||
"nix 0.23.1",
|
"nix 0.23.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||||
|
dependencies = [
|
||||||
|
"matches",
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-normalization",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.1"
|
version = "0.24.1"
|
||||||
@ -545,10 +569,10 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "machine-ip"
|
name = "matches"
|
||||||
version = "0.2.1"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8197ad28c61566fb74b2167563865906215fbc32c61fd866bd54e7c195eb84ed"
|
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
@ -705,6 +729,12 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "percent-encoding"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@ -839,7 +869,6 @@ dependencies = [
|
|||||||
name = "raspi-oled"
|
name = "raspi-oled"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dht-hal",
|
|
||||||
"display-interface-spi",
|
"display-interface-spi",
|
||||||
"embedded-graphics",
|
"embedded-graphics",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
@ -847,7 +876,6 @@ dependencies = [
|
|||||||
"image",
|
"image",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-embedded-hal",
|
"linux-embedded-hal",
|
||||||
"machine-ip",
|
|
||||||
"rppal 0.13.1",
|
"rppal 0.13.1",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"serde",
|
"serde",
|
||||||
@ -856,6 +884,7 @@ dependencies = [
|
|||||||
"ssd1351",
|
"ssd1351",
|
||||||
"time 0.3.9",
|
"time 0.3.9",
|
||||||
"time-tz",
|
"time-tz",
|
||||||
|
"ureq",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1077,6 +1106,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ssd1351"
|
name = "ssd1351"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
source = "git+https://github.com/FliegendeWurst/ssd1351-rust#9192fde637a2cc672e27ed1dc324f82e6bb65f72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"display-interface",
|
"display-interface",
|
||||||
@ -1199,12 +1229,67 @@ dependencies = [
|
|||||||
"time 0.3.9",
|
"time 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-normalization"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ureq"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9399fa2f927a3d327187cbd201480cee55bee6ac5d3c77dd27f0c6814cff16d5"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"chunked_transfer",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"matches",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "raspi-oled"
|
name = "raspi-oled"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["chux0519 <chuxdesign@hotmail.com>"]
|
authors = ["FliegendeWurst <2012gdwu@posteo.de>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@ -10,11 +10,8 @@ edition = "2018"
|
|||||||
embedded-graphics = "0.7.1"
|
embedded-graphics = "0.7.1"
|
||||||
linux-embedded-hal = "0.3.0"
|
linux-embedded-hal = "0.3.0"
|
||||||
embedded-hal = "0.2.5"
|
embedded-hal = "0.2.5"
|
||||||
machine-ip = "0.2.1"
|
|
||||||
#ssd1306 = "0.6.0"
|
|
||||||
libc = "0.2.98"
|
libc = "0.2.98"
|
||||||
gpio-cdev = "0.4"
|
gpio-cdev = "0.4"
|
||||||
dht-hal = "0.0.1"
|
|
||||||
rusqlite = "0.25.3"
|
rusqlite = "0.25.3"
|
||||||
time = { version = "0.3.9", features = ["parsing"] }
|
time = { version = "0.3.9", features = ["parsing"] }
|
||||||
time-tz = "1.0.1"
|
time-tz = "1.0.1"
|
||||||
@ -23,9 +20,9 @@ serde_json = "1.0.79"
|
|||||||
serde_derive = "1.0.136"
|
serde_derive = "1.0.136"
|
||||||
serde = "1.0.136"
|
serde = "1.0.136"
|
||||||
rppal = { version = "0.13.1", features = ["hal"] }
|
rppal = { version = "0.13.1", features = ["hal"] }
|
||||||
#ssd1351 = "0.4.0"
|
ssd1351 = { git = "https://github.com/FliegendeWurst/ssd1351-rust" }
|
||||||
ssd1351 = { path = "../ssd1351-rust" }
|
|
||||||
display-interface-spi = "0.4.1"
|
display-interface-spi = "0.4.1"
|
||||||
|
ureq = { version = "2.4.0", default-features = false }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
17
README.md
17
README.md
@ -1,17 +1,20 @@
|
|||||||
# raspi demo for oled ssd1306 display
|
# raspi demo for OLED ssd1351 display
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
> nix-shell
|
> nix-shell
|
||||||
>
|
|
||||||
> rustup target add arm-unknown-linux-musleabihf
|
> rustup target add arm-unknown-linux-musleabihf
|
||||||
>
|
|
||||||
> cargo build --release --target arm-unknown-linux-musleabihf
|
> cargo build --release --target arm-unknown-linux-musleabihf
|
||||||
|
> scp target/arm-unknown-linux-musleabihf/release/{display_all,display_off,refresh_json,take_measurement} 'pi@raspberrypi:~'
|
||||||
Then scp the release file to your raspi.
|
> # on the Pi:
|
||||||
|
> patchelf --set-interpreter /lib/ld-linux-armhf.so.3 display_all
|
||||||
|
> ./display_off on
|
||||||
|
> ./display_all sensors.db events.json temps
|
||||||
|
```
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
![picture](./images/01.jpg)
|
![picture](./images/temps.png)
|
||||||
|
|
||||||
![primitive](./images/02.jpg)
|
![primitive](./images/events.png)
|
||||||
|
16
events_weekly.json
Normal file
16
events_weekly.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"weekly": [
|
||||||
|
{
|
||||||
|
"name": "Example 1",
|
||||||
|
"day": 0,
|
||||||
|
"hour": 9,
|
||||||
|
"minute": 45,
|
||||||
|
"duration": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Example 2",
|
||||||
|
"day": 3,
|
||||||
|
"hour": 11,
|
||||||
|
"minute": 15,
|
||||||
|
"duration": 45
|
||||||
|
}
|
||||||
|
]
|
BIN
images/events.png
Normal file
BIN
images/events.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
images/temps.png
Normal file
BIN
images/temps.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 843 B |
@ -1,4 +1,4 @@
|
|||||||
use std::fs;
|
use std::{fs, ops::Sub, time::Duration, fmt::Debug};
|
||||||
|
|
||||||
use display_interface_spi::SPIInterfaceNoCS;
|
use display_interface_spi::SPIInterfaceNoCS;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
@ -7,17 +7,15 @@ use embedded_graphics::{
|
|||||||
ascii::{FONT_10X20, FONT_5X8, FONT_6X9, FONT_9X15},
|
ascii::{FONT_10X20, FONT_5X8, FONT_6X9, FONT_9X15},
|
||||||
MonoTextStyleBuilder,
|
MonoTextStyleBuilder,
|
||||||
},
|
},
|
||||||
pixelcolor::{BinaryColor, Rgb565},
|
pixelcolor::{Rgb565},
|
||||||
prelude::{OriginDimensions, Point, Primitive, Size},
|
prelude::{Point, Primitive},
|
||||||
primitives::{PrimitiveStyleBuilder, Rectangle},
|
primitives::{PrimitiveStyleBuilder, Rectangle},
|
||||||
text::Text,
|
text::{Text, renderer::CharacterStyle},
|
||||||
Drawable,
|
Drawable,
|
||||||
};
|
};
|
||||||
use image::{ImageBuffer, Rgb};
|
use raspi_oled::FrameOutput;
|
||||||
use linux_embedded_hal::I2cdev;
|
|
||||||
use rppal::{
|
use rppal::{
|
||||||
gpio::Gpio,
|
gpio::Gpio,
|
||||||
hal::Delay,
|
|
||||||
spi::{Bus, Mode, SlaveSelect, Spi},
|
spi::{Bus, Mode, SlaveSelect, Spi},
|
||||||
};
|
};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
@ -37,6 +35,7 @@ struct Events {
|
|||||||
struct Event {
|
struct Event {
|
||||||
name: String,
|
name: String,
|
||||||
start_time: String,
|
start_time: String,
|
||||||
|
end_time: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -83,7 +82,7 @@ fn main() {
|
|||||||
hour.sort();
|
hour.sort();
|
||||||
let mut min = hour[1];
|
let mut min = hour[1];
|
||||||
let mut max = hour[hour.len() - 2];
|
let mut max = hour[hour.len() - 2];
|
||||||
println!("min {} max {}", min, max);
|
//println!("min {} max {}", min, max);
|
||||||
// sanity check value
|
// sanity check value
|
||||||
if max > 300 {
|
if max > 300 {
|
||||||
if vals.is_empty() {
|
if vals.is_empty() {
|
||||||
@ -98,27 +97,22 @@ fn main() {
|
|||||||
global_max = max.max(global_max);
|
global_max = max.max(global_max);
|
||||||
vals.push((min, max));
|
vals.push((min, max));
|
||||||
}
|
}
|
||||||
println!("global {} | {}", global_min, global_max);
|
//println!("global {} | {}", global_min, global_max);
|
||||||
|
|
||||||
let hour = time.hour();
|
|
||||||
let minute = time.minute();
|
|
||||||
//let i2c = I2cdev::new("/dev/i2c-1").unwrap();
|
|
||||||
//let interface = I2CDisplayInterface::new(i2c);
|
|
||||||
//let mut disp = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0).into_buffered_graphics_mode();
|
|
||||||
//disp.init().unwrap();
|
|
||||||
//let mut disp = FrameOutput { buffer: ImageBuffer::new(128, 64) };
|
|
||||||
let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 19660800, Mode::Mode0).unwrap();
|
let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 19660800, Mode::Mode0).unwrap();
|
||||||
let gpio = Gpio::new().unwrap();
|
let gpio = Gpio::new().unwrap();
|
||||||
let dc = gpio.get(25).unwrap().into_output();
|
let dc = gpio.get(25).unwrap().into_output();
|
||||||
let mut rst = gpio.get(27).unwrap().into_output();
|
|
||||||
|
|
||||||
// Init SPI
|
|
||||||
let spii = SPIInterfaceNoCS::new(spi, dc);
|
let spii = SPIInterfaceNoCS::new(spi, dc);
|
||||||
let mut disp = ssd1351::display::display::Ssd1351::new(spii);
|
let disp = ssd1351::display::display::Ssd1351::new(spii);
|
||||||
|
//let mut disp = FrameOutput::new(128, 128);
|
||||||
|
|
||||||
// Reset & init
|
let mut disp = draw(disp, time, rh, temp, events, &args, global_min, global_max, vals);
|
||||||
//disp.reset(&mut rst, &mut Delay).unwrap();
|
let _ = disp.flush();
|
||||||
//disp.turn_on().unwrap();
|
//disp.buffer.save("/tmp/x.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw<D: DrawTarget<Color = Rgb565>>(mut disp: D, time: OffsetDateTime, rh: i64, temp: i64, events: Events, args: &[String], global_min: i32, global_max: i32, mut vals: Vec<(i32, i32)>) -> D where <D as DrawTarget>::Error: Debug {
|
||||||
|
let hour = time.hour();
|
||||||
|
let minute = time.minute();
|
||||||
|
|
||||||
let text_style_clock = MonoTextStyleBuilder::new()
|
let text_style_clock = MonoTextStyleBuilder::new()
|
||||||
.font(&FONT_10X20)
|
.font(&FONT_10X20)
|
||||||
@ -128,7 +122,7 @@ fn main() {
|
|||||||
.font(&FONT_9X15)
|
.font(&FONT_9X15)
|
||||||
.text_color(Rgb565::new(0xff, 0xff, 0xff))
|
.text_color(Rgb565::new(0xff, 0xff, 0xff))
|
||||||
.build();
|
.build();
|
||||||
let text_style3 = MonoTextStyleBuilder::new()
|
let mut text_style_6x9 = MonoTextStyleBuilder::new()
|
||||||
.font(&FONT_6X9)
|
.font(&FONT_6X9)
|
||||||
.text_color(Rgb565::new(0xff, 0xff, 0xff))
|
.text_color(Rgb565::new(0xff, 0xff, 0xff))
|
||||||
.build();
|
.build();
|
||||||
@ -163,7 +157,7 @@ fn main() {
|
|||||||
Text::new(&rh, Point::new(64 + 3, 64 - 4), text_style2)
|
Text::new(&rh, Point::new(64 + 3, 64 - 4), text_style2)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Text::new("%", Point::new(64 + 3 + 18, 64 - 4), text_style3)
|
Text::new("%", Point::new(64 + 3 + 18, 64 - 4), text_style_6x9)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let temp_int = format!("{:02}", temp / 10);
|
let temp_int = format!("{:02}", temp / 10);
|
||||||
@ -175,7 +169,7 @@ fn main() {
|
|||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let temp_fract = format!("{}", temp % 10);
|
let temp_fract = format!("{}", temp % 10);
|
||||||
Text::new(&temp_fract, Point::new(64 + 32 + 3 + 18 + 2, 64 - 4), text_style3)
|
Text::new(&temp_fract, Point::new(64 + 32 + 3 + 18 + 2, 64 - 4), text_style_6x9)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -227,7 +221,7 @@ fn main() {
|
|||||||
("S", "o"),
|
("S", "o"),
|
||||||
];
|
];
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
Text::new(days[day].0, (x + 12 * i + 4, y + 6).into(), text_style3)
|
Text::new(days[day].0, (x + 12 * i + 4, y + 6).into(), text_style_6x9)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Text::new(days[day].1, (x + 12 * i + 10, y + 6).into(), text_style4)
|
Text::new(days[day].1, (x + 12 * i + 10, y + 6).into(), text_style4)
|
||||||
@ -240,9 +234,12 @@ fn main() {
|
|||||||
// events
|
// events
|
||||||
let mut all_events = vec![];
|
let mut all_events = vec![];
|
||||||
for event in events.weekly {
|
for event in events.weekly {
|
||||||
all_events.push((event.day, event.hour, event.minute, event.duration, event.name));
|
let mut event_time = time.clone();
|
||||||
|
while event_time.weekday().number_days_from_monday() as i32 != event.day {
|
||||||
|
event_time += Duration::from_secs(24 * 60 * 60);
|
||||||
|
}
|
||||||
|
all_events.push((event.day, event.hour, event.minute, event.duration, event.name, event_time.to_julian_day()));
|
||||||
}
|
}
|
||||||
let today = time.date().to_julian_day();
|
|
||||||
let format = format_description::parse("[year]-[month]-[day]T[hour]:[minute]:[second]").unwrap();
|
let format = format_description::parse("[year]-[month]-[day]T[hour]:[minute]:[second]").unwrap();
|
||||||
for event in events.events {
|
for event in events.events {
|
||||||
let dt = PrimitiveDateTime::parse(&event.start_time, &format)
|
let dt = PrimitiveDateTime::parse(&event.start_time, &format)
|
||||||
@ -250,21 +247,41 @@ fn main() {
|
|||||||
.assume_timezone(BERLIN)
|
.assume_timezone(BERLIN)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let julian_day = dt.to_julian_day();
|
let julian_day = dt.to_julian_day();
|
||||||
if dt < time || julian_day - today > 4 {
|
if dt < time {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
let duration = if let Some(end_time) = event.end_time.as_ref() {
|
||||||
|
let dt2 = PrimitiveDateTime::parse(end_time, &format)
|
||||||
|
.unwrap()
|
||||||
|
.assume_timezone(BERLIN)
|
||||||
|
.unwrap();
|
||||||
|
(dt2.sub(dt).as_seconds_f32() / 60.0) as i32
|
||||||
|
} else {
|
||||||
|
30
|
||||||
|
};
|
||||||
all_events.push((
|
all_events.push((
|
||||||
dt.weekday().number_days_from_monday() as _,
|
dt.weekday().number_days_from_monday() as _,
|
||||||
dt.hour() as _,
|
dt.hour() as _,
|
||||||
dt.minute() as _,
|
dt.minute() as _,
|
||||||
30,
|
duration,
|
||||||
event.name,
|
event.name,
|
||||||
)); // TODO length
|
julian_day,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
let today = time.date().to_julian_day();
|
||||||
let weekday = time.weekday().number_days_from_monday() as i32;
|
let weekday = time.weekday().number_days_from_monday() as i32;
|
||||||
all_events.sort_by_key(|x| (((x.0 + 7) - weekday) % 7, x.1, x.2));
|
all_events.sort_by_key(|x| (x.5, ((x.0 + 7) - weekday) % 7, x.1, x.2));
|
||||||
println!("{:?}", all_events);
|
println!("{:?}", all_events);
|
||||||
let mut time_until_first = None;
|
let mut time_until_first = None;
|
||||||
|
let colors = vec![
|
||||||
|
Rgb565::new(0xff >> 3, 0xff >> 2, 0x00 >> 3),
|
||||||
|
Rgb565::new(0xff >> 3, 0x00 >> 2, 0xff >> 3),
|
||||||
|
Rgb565::new(0x00 >> 3, 0xff >> 2, 0xff >> 3),
|
||||||
|
Rgb565::new(0xff >> 3, 0x00 >> 2, 0x00 >> 3),
|
||||||
|
Rgb565::new(0x00 >> 3, 0xff >> 2, 0x00 >> 3),
|
||||||
|
Rgb565::new(0x00 >> 3, 0x00 >> 2, 0xff >> 3),
|
||||||
|
Rgb565::new(0xff >> 3, 0xff >> 2, 0xff >> 3),
|
||||||
|
];
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
let day = (weekday + i) % 7;
|
let day = (weekday + i) % 7;
|
||||||
for hour in 0..24 {
|
for hour in 0..24 {
|
||||||
@ -274,11 +291,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 && hour == time.hour() as i32 && minute == (time.minute() as i32 / 6) * 6 {
|
if i == 0 && hour == time.hour() as i32 && minute == (time.minute() as i32 / 6) * 6 {
|
||||||
bits.push((i, hour, minute / 6, Rgb565::new(0xff, 0x00, 0xff)));
|
bits.push((i, hour, minute / 6, Some(Rgb565::new(0xff, 0x00, 0xff))));
|
||||||
}
|
}
|
||||||
|
|
||||||
for event in &all_events {
|
for (event_idx, event) in all_events.iter().enumerate() {
|
||||||
if event.0 != day {
|
if event.0 != day || event.5 < today || event.5 - today > 4 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let event_start = event.1 * 60 + event.2;
|
let event_start = event.1 * 60 + event.2;
|
||||||
@ -286,9 +303,9 @@ fn main() {
|
|||||||
let now = hour * 60 + minute;
|
let now = hour * 60 + minute;
|
||||||
let now2 = hour * 60 + minute + 6;
|
let now2 = hour * 60 + minute + 6;
|
||||||
if now2 > event_start && now < event_end {
|
if now2 > event_start && now < event_end {
|
||||||
bits.push((i, hour, minute / 6, Rgb565::new(0xff, 0xff, 0x10)));
|
bits.push((i, hour, minute / 6, colors.get(event_idx).copied()));
|
||||||
}
|
}
|
||||||
if time_until_first.is_none() {
|
if time_until_first.is_none() && (i > 0 || event.1 > time.hour() as i32 || (event.1 == time.hour() as i32 && event.2 >= time.minute() as i32)) {
|
||||||
time_until_first = Some(
|
time_until_first = Some(
|
||||||
((i * 24 + event.1) * 60 + event.2) * 60
|
((i * 24 + event.1) * 60 + event.2) * 60
|
||||||
- (time.hour() as i32 * 60 + time.minute() as i32) * 60,
|
- (time.hour() as i32 * 60 + time.minute() as i32) * 60,
|
||||||
@ -302,14 +319,24 @@ fn main() {
|
|||||||
// calculate position
|
// calculate position
|
||||||
let x = x + 4 + d * 12 + m;
|
let x = x + 4 + d * 12 + m;
|
||||||
let y = y + 8 + h;
|
let y = y + 8 + h;
|
||||||
disp.fill_solid(&Rectangle::new((x, y).into(), (1, 1).into()), color)
|
disp.fill_solid(&Rectangle::new((x, y).into(), (1, 1).into()), color.unwrap_or(Rgb565::new(0xff, 0xff, 0x10)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
//Rectangle::new((x, y).into(), (1, 1).into()).into_styled(rect_style).draw(&mut disp).unwrap();
|
//Rectangle::new((x, y).into(), (1, 1).into()).into_styled(rect_style).draw(&mut disp).unwrap();
|
||||||
}
|
}
|
||||||
if args[3] == "events" {
|
if args[3] == "events" {
|
||||||
for (i, event) in all_events.iter().take(7).enumerate() {
|
for (i, event) in all_events.iter().take(7).enumerate() {
|
||||||
let text = if event.4.len() > 10 { &event.4[0..10] } else { &event.4 };
|
let text = if event.4.len() > 19 { &event.4[0..19] } else { &event.4 };
|
||||||
Text::new(text, (x + 2, y + 64 + 9 * i as i32 + 5).into(), text_style3)
|
let day = event.0 as usize;
|
||||||
|
let y = y + 64 + 9 * i as i32 + 5;
|
||||||
|
text_style_6x9.set_text_color(Some(Rgb565::new(0xff, 0xff, 0xff)));
|
||||||
|
Text::new(days[day].0, (x, y).into(), text_style_6x9)
|
||||||
|
.draw(&mut disp)
|
||||||
|
.unwrap();
|
||||||
|
Text::new(days[day].1, (x + 6, y).into(), text_style4)
|
||||||
|
.draw(&mut disp)
|
||||||
|
.unwrap();
|
||||||
|
text_style_6x9.set_text_color(Some(colors[i]));
|
||||||
|
Text::new(text, (x + 14, y).into(), text_style_6x9)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -331,14 +358,14 @@ fn main() {
|
|||||||
Text::new(
|
Text::new(
|
||||||
&format!("{}", global_max as f32 / 10.0),
|
&format!("{}", global_max as f32 / 10.0),
|
||||||
(100, 64 + 10).into(),
|
(100, 64 + 10).into(),
|
||||||
text_style3,
|
text_style_6x9,
|
||||||
)
|
)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Text::new(
|
Text::new(
|
||||||
&format!("{}", global_min as f32 / 10.0),
|
&format!("{}", global_min as f32 / 10.0),
|
||||||
(100, 64 + 50).into(),
|
(100, 64 + 50).into(),
|
||||||
text_style3,
|
text_style_6x9,
|
||||||
)
|
)
|
||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -360,63 +387,6 @@ fn main() {
|
|||||||
.draw(&mut disp)
|
.draw(&mut disp)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
sleep(Duration::from_secs(2));
|
|
||||||
disp.clear();
|
|
||||||
|
|
||||||
let base_y = 0.0;
|
disp
|
||||||
let max_dy = 32.0;
|
|
||||||
let mut tick = 0;
|
|
||||||
loop {
|
|
||||||
let y = if tick % 32 < 16 {
|
|
||||||
base_y + (tick % 16) as f32 / 16.0 * max_dy
|
|
||||||
} else {
|
|
||||||
base_y + max_dy - (tick % 16) as f32 / 16.0 * max_dy
|
|
||||||
} as i32;
|
|
||||||
tick += 1;
|
|
||||||
Line::new(Point::new(8, y + 16), Point::new(8 + 16, y + 16))
|
|
||||||
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
|
|
||||||
.draw(&mut disp).unwrap();
|
|
||||||
Line::new(Point::new(8, y + 16), Point::new(8 + 8, y))
|
|
||||||
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
|
|
||||||
.draw(&mut disp).unwrap();
|
|
||||||
|
|
||||||
Line::new(Point::new(8 + 16, y + 16), Point::new(8 + 8, y))
|
|
||||||
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
|
|
||||||
.draw(&mut disp).unwrap();
|
|
||||||
|
|
||||||
Rectangle::new(Point::new(48, y), Size::new(16, 16))
|
|
||||||
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
|
|
||||||
.draw(&mut disp).unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
Circle::new(Point::new(88, y), 16)
|
|
||||||
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
|
|
||||||
.draw(&mut disp).unwrap();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Text::new(&format!("Hello from frame {}", tick), Point::new(0, 56), text_style)
|
|
||||||
.draw(&mut disp)
|
|
||||||
.unwrap();
|
|
||||||
*/
|
|
||||||
disp.flush().unwrap();
|
|
||||||
|
|
||||||
sleep(Duration::from_millis(10));
|
|
||||||
|
|
||||||
disp.clear();
|
|
||||||
|
|
||||||
/*
|
|
||||||
let im: ImageRaw<BinaryColor> = ImageRaw::new(IMG_DATA, 64);
|
|
||||||
let img = Image::new(&im, Point::new(32, 0));
|
|
||||||
img.draw(&mut disp).unwrap();
|
|
||||||
disp.flush().unwrap();
|
|
||||||
|
|
||||||
sleep(Duration::from_secs(2));
|
|
||||||
disp.clear();
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
let _ = disp.flush();
|
|
||||||
//disp.buffer.save("/tmp/frame.png").unwrap();
|
|
||||||
}
|
}
|
||||||
|
22
src/bin/refresh_json.rs
Normal file
22
src/bin/refresh_json.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use std::{error::Error, fs};
|
||||||
|
|
||||||
|
static WEEKLY: &'static str = include_str!("../../events_weekly.json");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let url = "http://nixos.fritz.box:12783/custom/event_alerts";
|
||||||
|
|
||||||
|
if let Ok(json) = get_json(url) {
|
||||||
|
let mut buf = String::new();
|
||||||
|
buf += "{";
|
||||||
|
buf += "\"events\": ";
|
||||||
|
buf += &json;
|
||||||
|
buf += ",";
|
||||||
|
buf += WEEKLY;
|
||||||
|
buf += "}";
|
||||||
|
fs::write("events.json", buf.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_json(url: &str) -> Result<String, Box<dyn Error>> {
|
||||||
|
Ok(ureq::get(url).call()?.into_string()?)
|
||||||
|
}
|
40
src/lib.rs
40
src/lib.rs
@ -3,7 +3,47 @@ use std::{
|
|||||||
time::{self, Duration},
|
time::{self, Duration},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use embedded_graphics::{pixelcolor::Rgb565, draw_target::DrawTarget, prelude::{OriginDimensions, Size, RgbColor}};
|
||||||
use gpio_cdev::{EventType, Line, LineRequestFlags};
|
use gpio_cdev::{EventType, Line, LineRequestFlags};
|
||||||
|
use image::{ImageBuffer, Rgb};
|
||||||
|
|
||||||
|
pub struct FrameOutput {
|
||||||
|
pub buffer: ImageBuffer<Rgb<u8>, Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FrameOutput {
|
||||||
|
pub fn new(width: u32, height: u32) -> Self {
|
||||||
|
FrameOutput {
|
||||||
|
buffer: ImageBuffer::new(width, height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrawTarget for FrameOutput {
|
||||||
|
type Color = Rgb565;
|
||||||
|
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
|
||||||
|
{
|
||||||
|
for pos in pixels {
|
||||||
|
if pos.0.x < 0 || pos.0.y < 0 || pos.0.x as u32 >= self.buffer.width() || pos.0.y as u32 >= self.buffer.height() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.buffer.put_pixel(pos.0.x as u32, pos.0.y as u32, Rgb([pos.1.r() << 3, pos.1.g() << 2, pos.1.b() << 3]));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OriginDimensions for FrameOutput {
|
||||||
|
fn size(&self) -> Size {
|
||||||
|
Size::new(self.buffer.width(), self.buffer.height())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn read_events(line: &gpio_cdev::Line, timeout: std::time::Duration) -> Result<Vec<(u64, EventType)>, SensorError> {
|
fn read_events(line: &gpio_cdev::Line, timeout: std::time::Duration) -> Result<Vec<(u64, EventType)>, SensorError> {
|
||||||
let input = line.request(LineRequestFlags::INPUT, 0, "read-data")?;
|
let input = line.request(LineRequestFlags::INPUT, 0, "read-data")?;
|
||||||
|
234
src/main.rs
234
src/main.rs
@ -1,136 +1,6 @@
|
|||||||
use embedded_graphics::{
|
|
||||||
draw_target::DrawTarget,
|
|
||||||
pixelcolor::BinaryColor,
|
|
||||||
prelude::{OriginDimensions, Size},
|
|
||||||
primitives::Rectangle,
|
|
||||||
};
|
|
||||||
use image::{ImageBuffer, Rgb};
|
|
||||||
use rusqlite::Connection;
|
|
||||||
|
|
||||||
struct FrameOutput {
|
|
||||||
buffer: ImageBuffer<Rgb<u8>, Vec<u8>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DrawTarget for FrameOutput {
|
|
||||||
type Color = BinaryColor;
|
|
||||||
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
|
|
||||||
{
|
|
||||||
for pos in pixels {
|
|
||||||
if pos.0.x < 0 || pos.0.y < 0 || pos.0.x >= 128 || pos.0.y >= 64 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let color = if pos.1 == BinaryColor::On {
|
|
||||||
Rgb([0, 255, 255])
|
|
||||||
} else {
|
|
||||||
Rgb([0, 0, 0])
|
|
||||||
};
|
|
||||||
self.buffer.put_pixel(pos.0.x as u32, pos.0.y as u32, color);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OriginDimensions for FrameOutput {
|
|
||||||
fn size(&self) -> Size {
|
|
||||||
Size::new(self.buffer.width(), self.buffer.height())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let args = std::env::args().collect::<Vec<_>>();
|
|
||||||
if args.len() < 2 {
|
|
||||||
panic!("missing argument: database path");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut disp = FrameOutput {
|
|
||||||
buffer: ImageBuffer::new(128, 64),
|
|
||||||
};
|
|
||||||
|
|
||||||
let database = Connection::open(&args[1]).expect("failed to open database");
|
|
||||||
|
|
||||||
let mut query = database
|
|
||||||
.prepare("SELECT celsius FROM sensor_readings ORDER BY sensor_readings.time DESC LIMIT 288")
|
|
||||||
.unwrap();
|
|
||||||
let mut temps: Vec<i32> = query
|
|
||||||
.query_map([], |r| Ok(r.get(0)))
|
|
||||||
.unwrap()
|
|
||||||
.map(Result::unwrap)
|
|
||||||
.map(Result::unwrap)
|
|
||||||
.collect();
|
|
||||||
let mut global_min = 1000;
|
|
||||||
let mut global_max = 0;
|
|
||||||
let mut vals: Vec<(i32, i32)> = vec![];
|
|
||||||
for hour in temps.chunks_mut(6) {
|
|
||||||
hour.sort();
|
|
||||||
let min = hour[1];
|
|
||||||
let mut max = hour[hour.len() - 2];
|
|
||||||
println!("min {} max {}", min, max);
|
|
||||||
// sanity check value
|
|
||||||
if max > 300 {
|
|
||||||
if vals.is_empty() {
|
|
||||||
max = min;
|
|
||||||
} else {
|
|
||||||
max = vals.last().unwrap().1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
global_min = min.min(global_min);
|
|
||||||
global_max = max.max(global_max);
|
|
||||||
vals.push((min, max));
|
|
||||||
}
|
|
||||||
println!("global {} | {}", global_min, global_max);
|
|
||||||
let diff = global_max - global_min;
|
|
||||||
let x = 1;
|
|
||||||
let y = 1;
|
|
||||||
let scaley = 64;
|
|
||||||
let scalex = 2;
|
|
||||||
vals.reverse();
|
|
||||||
for (i, (a, b)) in vals.into_iter().enumerate() {
|
|
||||||
let x = x + i as i32 * scalex;
|
|
||||||
let y1 = y + (global_max - b) * scaley / diff;
|
|
||||||
let y2 = y + (global_max - a) * scaley / diff;
|
|
||||||
let height = y2 - y1 + 1;
|
|
||||||
disp.fill_solid(
|
|
||||||
&Rectangle::new((x, y1).into(), (scalex as u32, height as u32).into()),
|
|
||||||
BinaryColor::On,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
disp.buffer.save("/tmp/frame.png").unwrap();
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
use dht_hal::{Dht22, Reading};
|
|
||||||
use embedded_graphics::image::{Image, ImageRaw};
|
|
||||||
use embedded_graphics::mono_font::iso_8859_7::FONT_9X18;
|
|
||||||
use embedded_graphics::pixelcolor::BinaryColor;
|
|
||||||
use embedded_graphics::prelude::*;
|
|
||||||
use embedded_graphics::primitives::{Circle, Line, PrimitiveStyle, Rectangle};
|
|
||||||
|
|
||||||
use embedded_graphics::{
|
|
||||||
mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder},
|
|
||||||
text::Text,
|
|
||||||
};
|
|
||||||
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
|
||||||
use embedded_hal::prelude::_embedded_hal_blocking_i2c_Write;
|
|
||||||
use gpio_cdev::{Chip, EventRequestFlags, EventType, LineRequestFlags};
|
|
||||||
use linux_embedded_hal::i2cdev::core::I2CDevice;
|
use linux_embedded_hal::i2cdev::core::I2CDevice;
|
||||||
use linux_embedded_hal::i2cdev::linux::LinuxI2CError;
|
use linux_embedded_hal::i2cdev::linux::LinuxI2CError;
|
||||||
use linux_embedded_hal::{Delay, I2cdev};
|
use linux_embedded_hal::I2cdev;
|
||||||
use machine_ip;
|
|
||||||
use rusqlite::{params, Connection};
|
|
||||||
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
|
|
||||||
use std::intrinsics::transmute;
|
|
||||||
use std::thread::sleep;
|
|
||||||
use std::time::{Duration, SystemTime};
|
|
||||||
use std::{env, mem, time};
|
|
||||||
|
|
||||||
static IMG_DATA: &[u8; 512] = include_bytes!("../rust.raw");
|
|
||||||
|
|
||||||
const CCS811_ADDR: u8 = 0x5A; // or 0x5B
|
const CCS811_ADDR: u8 = 0x5A; // or 0x5B
|
||||||
|
|
||||||
@ -218,6 +88,108 @@ enum CCS811DriveMode {
|
|||||||
Every250Milliseconds = 4,
|
Every250Milliseconds = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let i2c = I2cdev::new("/dev/i2c-1").unwrap();
|
||||||
|
let mut ccs = CCS811::new(i2c, CCS811_ADDR);
|
||||||
|
println!("HW ID, should be 0x81 {:x}", ccs.hardware_id());
|
||||||
|
println!("Error code, should be None: {:?}", ccs.check_for_error());
|
||||||
|
println!("app valid = {:?}", ccs.app_valid());
|
||||||
|
println!("baseline = {:x}", ccs.get_baseline());
|
||||||
|
println!("reading {:?}", ccs.get_reading());
|
||||||
|
println!("setting drive mode to 1: {:?}", ccs.set_drive_mode(CCS811DriveMode::EverySecond));
|
||||||
|
|
||||||
|
/*
|
||||||
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
if args.len() < 2 {
|
||||||
|
panic!("missing argument: database path");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut disp = FrameOutput {
|
||||||
|
buffer: ImageBuffer::new(128, 64),
|
||||||
|
};
|
||||||
|
|
||||||
|
let database = Connection::open(&args[1]).expect("failed to open database");
|
||||||
|
|
||||||
|
let mut query = database
|
||||||
|
.prepare("SELECT celsius FROM sensor_readings ORDER BY sensor_readings.time DESC LIMIT 288")
|
||||||
|
.unwrap();
|
||||||
|
let mut temps: Vec<i32> = query
|
||||||
|
.query_map([], |r| Ok(r.get(0)))
|
||||||
|
.unwrap()
|
||||||
|
.map(Result::unwrap)
|
||||||
|
.map(Result::unwrap)
|
||||||
|
.collect();
|
||||||
|
let mut global_min = 1000;
|
||||||
|
let mut global_max = 0;
|
||||||
|
let mut vals: Vec<(i32, i32)> = vec![];
|
||||||
|
for hour in temps.chunks_mut(6) {
|
||||||
|
hour.sort();
|
||||||
|
let min = hour[1];
|
||||||
|
let mut max = hour[hour.len() - 2];
|
||||||
|
println!("min {} max {}", min, max);
|
||||||
|
// sanity check value
|
||||||
|
if max > 300 {
|
||||||
|
if vals.is_empty() {
|
||||||
|
max = min;
|
||||||
|
} else {
|
||||||
|
max = vals.last().unwrap().1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_min = min.min(global_min);
|
||||||
|
global_max = max.max(global_max);
|
||||||
|
vals.push((min, max));
|
||||||
|
}
|
||||||
|
println!("global {} | {}", global_min, global_max);
|
||||||
|
let diff = global_max - global_min;
|
||||||
|
let x = 1;
|
||||||
|
let y = 1;
|
||||||
|
let scaley = 64;
|
||||||
|
let scalex = 2;
|
||||||
|
vals.reverse();
|
||||||
|
for (i, (a, b)) in vals.into_iter().enumerate() {
|
||||||
|
let x = x + i as i32 * scalex;
|
||||||
|
let y1 = y + (global_max - b) * scaley / diff;
|
||||||
|
let y2 = y + (global_max - a) * scaley / diff;
|
||||||
|
let height = y2 - y1 + 1;
|
||||||
|
disp.fill_solid(
|
||||||
|
&Rectangle::new((x, y1).into(), (scalex as u32, height as u32).into()),
|
||||||
|
BinaryColor::On,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
disp.buffer.save("/tmp/frame.png").unwrap();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
use dht_hal::{Dht22, Reading};
|
||||||
|
use embedded_graphics::image::{Image, ImageRaw};
|
||||||
|
use embedded_graphics::mono_font::iso_8859_7::FONT_9X18;
|
||||||
|
use embedded_graphics::pixelcolor::BinaryColor;
|
||||||
|
use embedded_graphics::prelude::*;
|
||||||
|
use embedded_graphics::primitives::{Circle, Line, PrimitiveStyle, Rectangle};
|
||||||
|
|
||||||
|
use embedded_graphics::{
|
||||||
|
mono_font::{ascii::FONT_6X10, MonoTextStyleBuilder},
|
||||||
|
text::Text,
|
||||||
|
};
|
||||||
|
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
||||||
|
use embedded_hal::prelude::_embedded_hal_blocking_i2c_Write;
|
||||||
|
use gpio_cdev::{Chip, EventRequestFlags, EventType, LineRequestFlags};
|
||||||
|
use linux_embedded_hal::i2cdev::core::I2CDevice;
|
||||||
|
use linux_embedded_hal::i2cdev::linux::LinuxI2CError;
|
||||||
|
use linux_embedded_hal::{Delay, I2cdev};
|
||||||
|
use machine_ip;
|
||||||
|
use rusqlite::{params, Connection};
|
||||||
|
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
|
||||||
|
use std::intrinsics::transmute;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
|
use std::{env, mem, time};
|
||||||
|
|
||||||
|
static IMG_DATA: &[u8; 512] = include_bytes!("../rust.raw");
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = env::args().collect::<Vec<_>>();
|
let args = env::args().collect::<Vec<_>>();
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
|
Loading…
Reference in New Issue
Block a user