pi-sensors: init
This commit is contained in:
parent
1f4344f43e
commit
2b11e14863
|
@ -56,6 +56,15 @@
|
||||||
mapHqHosts = true;
|
mapHqHosts = true;
|
||||||
hq.interface = "eth0";
|
hq.interface = "eth0";
|
||||||
hq.statistics.enable = true;
|
hq.statistics.enable = true;
|
||||||
|
pi-sensors = [ {
|
||||||
|
type = "dht22";
|
||||||
|
pin = 17;
|
||||||
|
location = "Tisch";
|
||||||
|
} {
|
||||||
|
type = "dht22";
|
||||||
|
pin = 23;
|
||||||
|
location = "Tisch2";
|
||||||
|
} ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nix = {
|
nix = {
|
||||||
|
|
|
@ -32,6 +32,7 @@ in {
|
||||||
./stats.nix
|
./stats.nix
|
||||||
./openwebrx.nix
|
./openwebrx.nix
|
||||||
./audio-server
|
./audio-server
|
||||||
|
./pi-sensors.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
options.c3d2 = with lib;
|
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 { };
|
openwebrx = prev.python3Packages.callPackage ./openwebrx.nix { };
|
||||||
|
|
||||||
dump1090_sdrplus = prev.callPackage ./dump1090.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