pi-sensors: init
This commit is contained in:
parent
1f4344f43e
commit
2b11e14863
|
@ -56,6 +56,15 @@
|
|||
mapHqHosts = true;
|
||||
hq.interface = "eth0";
|
||||
hq.statistics.enable = true;
|
||||
pi-sensors = [ {
|
||||
type = "dht22";
|
||||
pin = 17;
|
||||
location = "Tisch";
|
||||
} {
|
||||
type = "dht22";
|
||||
pin = 23;
|
||||
location = "Tisch2";
|
||||
} ];
|
||||
};
|
||||
|
||||
nix = {
|
||||
|
|
|
@ -32,6 +32,7 @@ in {
|
|||
./stats.nix
|
||||
./openwebrx.nix
|
||||
./audio-server
|
||||
./pi-sensors.nix
|
||||
];
|
||||
|
||||
options.c3d2 = with lib;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
{
|
||||
options.c3d2.pi-sensors = lib.mkOption {
|
||||
default = [];
|
||||
type = with lib.types; listOf (submodule ({ ... }: {
|
||||
options = {
|
||||
type = lib.mkOption {
|
||||
description = "Sensor type";
|
||||
type = enum ["dht22"];
|
||||
};
|
||||
pin = lib.mkOption {
|
||||
description = "GPIO pin";
|
||||
type = int;
|
||||
};
|
||||
location = lib.mkOption {
|
||||
description = "Sensor location";
|
||||
type = str;
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
config = lib.mkIf (config.c3d2.pi-sensors != []) {
|
||||
# GPIO requires access to /dev/mem
|
||||
security.wrappers.pi-sensors = {
|
||||
setuid = true;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
source = "${pkgs.pi-sensors}/bin/pi-sensors";
|
||||
};
|
||||
|
||||
services.collectd.plugins.exec = ''
|
||||
Exec "${config.services.collectd.user}" "/run/wrappers/bin/pi-sensors" "10"${lib.concatMapStrings (s: " \"${s}\"") (
|
||||
lib.concatMap ({ type, pin, location }:
|
||||
[ type (toString pin) location ]
|
||||
) config.c3d2.pi-sensors
|
||||
)}
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -8,4 +8,6 @@ final: prev:
|
|||
openwebrx = prev.python3Packages.callPackage ./openwebrx.nix { };
|
||||
|
||||
dump1090_sdrplus = prev.callPackage ./dump1090.nix { };
|
||||
|
||||
pi-sensors = prev.callPackage ./pi-sensors { };
|
||||
}
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "dht-hal-drv"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/voteblake/dht-hal-drv.git#ed6ea0177573b977545016036fa10ff3b52fd16f"
|
||||
dependencies = [
|
||||
"embedded-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
|
||||
[[package]]
|
||||
name = "pi-sensors"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"dht-hal-drv",
|
||||
"embedded-hal",
|
||||
"rppal",
|
||||
"spin_sleep",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rppal"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3225d01a8b7ae304645b4aa38f30061ee08539a1fc6458c68e2b55c803323679"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin_sleep"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a98101bdc3833e192713c2af0b0dd2614f50d1cf1f7a97c5221b7aac052acc7"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "pi-sensors"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
rppal = "0.13"
|
||||
embedded-hal = "0.2"
|
||||
void = "1"
|
||||
dht-hal-drv = "0.2"
|
||||
spin_sleep = "1"
|
||||
|
||||
[patch.crates-io]
|
||||
dht-hal-drv = { git = "https://github.com/voteblake/dht-hal-drv.git" }
|
|
@ -0,0 +1,8 @@
|
|||
{ rustPlatform }:
|
||||
|
||||
rustPlatform.buildRustPackage {
|
||||
name = "pi-sensors";
|
||||
version = "0.0.0";
|
||||
src = ./.;
|
||||
cargoSha256 = "0pihg88jx61a3bxm6n6h0fila34xgfnpgqrsdk4bw165bwmp5laq";
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use dht_hal_drv::{dht_split_init, dht_split_read, DhtType};
|
||||
use spin_sleep;
|
||||
use rppal::gpio::IoPin;
|
||||
|
||||
use crate::open_pin::OpenPin;
|
||||
use crate::{Measurement, Sensor};
|
||||
|
||||
pub struct DHT22 {
|
||||
location: Rc<String>,
|
||||
pin: OpenPin,
|
||||
}
|
||||
|
||||
impl DHT22 {
|
||||
pub fn new(pin: IoPin, location: String) -> Self {
|
||||
DHT22 {
|
||||
location: Rc::new(location),
|
||||
pin: OpenPin::new(pin),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sensor for DHT22 {
|
||||
fn read(&mut self) -> Vec<crate::Measurement> {
|
||||
let mut delay_us = |d: u16| {
|
||||
// We are using here more accurate delays than in std library
|
||||
spin_sleep::sleep(Duration::from_micros(d as u64));
|
||||
};
|
||||
|
||||
self.pin.switch_output();
|
||||
if let Err(_) = dht_split_init(&mut self.pin, &mut delay_us) {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
self.pin.switch_input();
|
||||
// match dht_read(DhtType::DHT22, &mut opin, &mut delay_us) {
|
||||
match dht_split_read(DhtType::DHT22, &mut self.pin, &mut delay_us) {
|
||||
Ok(readings) => vec![
|
||||
Measurement::new(self.location.clone(), "temperature", readings.temperature()),
|
||||
Measurement::new(self.location.clone(), "humidity", readings.humidity()),
|
||||
],
|
||||
Err(_) =>
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use rppal::gpio::{Gpio, Mode};
|
||||
|
||||
mod open_pin;
|
||||
mod dht;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Measurement {
|
||||
pub location: Rc<String>,
|
||||
pub type_: &'static str,
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
impl Measurement {
|
||||
pub fn new<V: Into<f64>>(
|
||||
location: Rc<String>,
|
||||
type_: &'static str,
|
||||
value: V,
|
||||
) -> Self {
|
||||
Measurement {
|
||||
location, type_,
|
||||
value: value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Sensor {
|
||||
fn read(&mut self) -> Vec<Measurement>;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let hostname = std::fs::read("/proc/sys/kernel/hostname")
|
||||
.expect("hostname");
|
||||
let hostname = String::from_utf8_lossy(&hostname);
|
||||
let hostname = hostname.trim();
|
||||
let gpio = Gpio::new().expect("Can not init Gpio structure");
|
||||
|
||||
let mut args = std::env::args().skip(1);
|
||||
let interval: u64 = args.next()
|
||||
.expect("interval argument")
|
||||
.parse()
|
||||
.expect("interval integer");
|
||||
let interval = Duration::from_secs(interval);
|
||||
|
||||
let mut sensors: Vec<Box<dyn Sensor>> = vec![];
|
||||
while let Some(kind) = args.next() {
|
||||
match &kind[..] {
|
||||
"dht22" => {
|
||||
let pin: u8 = args.next()
|
||||
.expect("pin argument")
|
||||
.parse()
|
||||
.expect("pin integer");
|
||||
let location = args.next()
|
||||
.expect("location");
|
||||
let iopin = gpio
|
||||
.get(pin)
|
||||
.expect("Was not able to get Pin")
|
||||
.into_io(Mode::Input);
|
||||
let dht = dht::DHT22::new(iopin, location);
|
||||
sensors.push(Box::new(dht));
|
||||
}
|
||||
_ => panic!("Unknown sensor kind: {}", kind),
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
for sensor in &mut sensors {
|
||||
for m in sensor.read() {
|
||||
println!(
|
||||
"PUTVAL {}/{}-{}/{}-{} interval={} N:{}",
|
||||
hostname,
|
||||
"sensors", "sensors-pi",
|
||||
m.type_, m.location,
|
||||
interval.as_secs(),
|
||||
m.value
|
||||
);
|
||||
}
|
||||
}
|
||||
std::thread::sleep(interval);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
use embedded_hal::digital::v2::{InputPin, OutputPin};
|
||||
use rppal::gpio::{IoPin, Mode};
|
||||
use void;
|
||||
|
||||
/**
|
||||
* Raspberry pi does not have open drain pins so we have to emulate it.
|
||||
*/
|
||||
pub struct OpenPin {
|
||||
iopin: IoPin,
|
||||
mode: Mode,
|
||||
}
|
||||
|
||||
impl OpenPin {
|
||||
pub fn new(mut pin: IoPin) -> OpenPin {
|
||||
pin.set_mode(Mode::Input);
|
||||
OpenPin {
|
||||
iopin: pin,
|
||||
mode: Mode::Input,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn switch_input(&mut self) {
|
||||
if self.mode != Mode::Input {
|
||||
self.mode = Mode::Input;
|
||||
self.iopin.set_mode(Mode::Input);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn switch_output(&mut self) {
|
||||
if self.mode != Mode::Output {
|
||||
self.mode = Mode::Output;
|
||||
self.iopin.set_mode(Mode::Output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current rppal implementation does not support embedded_hal::gpio::v2 pins API.
|
||||
impl InputPin for OpenPin {
|
||||
type Error = void::Void;
|
||||
|
||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.iopin.is_high())
|
||||
}
|
||||
|
||||
/// Is the input pin low?
|
||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||
Ok(self.iopin.is_low())
|
||||
}
|
||||
}
|
||||
|
||||
// Current rppal implementation does not support embedded_hal::gpio::v2 pins API.
|
||||
impl OutputPin for OpenPin {
|
||||
type Error = void::Void;
|
||||
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
self.switch_output();
|
||||
self.iopin.set_low();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||
self.iopin.set_high();
|
||||
self.switch_input();
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue